lib-fints 1.4.0 → 1.4.2

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 (273) hide show
  1. package/dist/camtParser.js +18 -9
  2. package/dist/client.js +51 -35
  3. package/dist/config.js +10 -6
  4. package/dist/dataElements/AlphaNumeric.js +1 -1
  5. package/dist/dataElements/DataElement.js +2 -1
  6. package/dist/dataElements/Digits.js +1 -1
  7. package/dist/dataElements/Float.js +1 -1
  8. package/dist/dataElements/Numeric.js +2 -2
  9. package/dist/dataElements/Text.js +1 -1
  10. package/dist/dataGroups/Account.js +1 -1
  11. package/dist/dataGroups/Balance.js +2 -2
  12. package/dist/dataGroups/BankIdentification.js +1 -1
  13. package/dist/dataGroups/DataGroup.js +13 -6
  14. package/dist/dataGroups/InternationalAccount.js +1 -1
  15. package/dist/dataGroups/Money.js +1 -1
  16. package/dist/dataGroups/RefMessage.js +1 -1
  17. package/dist/dataGroups/SepaAccount.js +2 -2
  18. package/dist/dataGroups/SepaAccountParameters.js +2 -2
  19. package/dist/dataGroups/TimeStamp.js +1 -1
  20. package/dist/decoder.js +12 -6
  21. package/dist/dialog.js +33 -19
  22. package/dist/encoder.js +16 -4
  23. package/dist/format.js +2 -2
  24. package/dist/httpClient.js +4 -2
  25. package/dist/index.js +10 -10
  26. package/dist/interactions/balanceInteraction.js +2 -5
  27. package/dist/interactions/creditcardStatementInteraction.js +11 -11
  28. package/dist/interactions/customerInteraction.js +1 -1
  29. package/dist/interactions/endDialogInteraction.js +4 -4
  30. package/dist/interactions/initDialogInteraction.js +23 -20
  31. package/dist/interactions/portfolioInteraction.js +3 -3
  32. package/dist/interactions/sepaAccountInteraction.js +3 -3
  33. package/dist/interactions/statementInteractionCAMT.js +4 -4
  34. package/dist/interactions/statementInteractionMT940.js +4 -4
  35. package/dist/interactions/tanMediaInteraction.js +4 -4
  36. package/dist/message.js +51 -18
  37. package/dist/mt535parser.js +3 -5
  38. package/dist/mt940parser.js +18 -17
  39. package/dist/parser.js +1 -1
  40. package/dist/segment.js +12 -7
  41. package/dist/segmentDefinition.js +5 -2
  42. package/dist/segmentHeader.js +1 -1
  43. package/dist/segments/DIKKU.js +3 -3
  44. package/dist/segments/DKKKU.js +2 -2
  45. package/dist/segments/HIBPA.js +2 -2
  46. package/dist/segments/HICAZ.js +1 -1
  47. package/dist/segments/HICAZS.js +3 -3
  48. package/dist/segments/HIKAZS.js +7 -3
  49. package/dist/segments/HIKIM.js +1 -1
  50. package/dist/segments/HIKOM.js +1 -1
  51. package/dist/segments/HIPINS.js +3 -3
  52. package/dist/segments/HIRMG.js +1 -1
  53. package/dist/segments/HIRMS.js +1 -1
  54. package/dist/segments/HISAL.js +3 -3
  55. package/dist/segments/HISPAS.js +3 -4
  56. package/dist/segments/HISYN.js +1 -1
  57. package/dist/segments/HITAB.js +3 -3
  58. package/dist/segments/HITAN.js +3 -3
  59. package/dist/segments/HITANS.js +3 -3
  60. package/dist/segments/HIUPA.js +2 -2
  61. package/dist/segments/HIUPD.js +8 -4
  62. package/dist/segments/HKCAZ.js +3 -3
  63. package/dist/segments/HKIDN.js +1 -1
  64. package/dist/segments/HKKAZ.js +3 -3
  65. package/dist/segments/HKSAL.js +3 -3
  66. package/dist/segments/HKSPA.js +1 -1
  67. package/dist/segments/HKTAB.js +1 -1
  68. package/dist/segments/HKTAN.js +3 -3
  69. package/dist/segments/HKVVB.js +1 -1
  70. package/dist/segments/HKWPD.js +1 -1
  71. package/dist/segments/HNHBK.js +1 -1
  72. package/dist/segments/HNSHA.js +1 -1
  73. package/dist/segments/HNSHK.js +14 -6
  74. package/dist/segments/HNVSK.js +10 -6
  75. package/dist/segments/registry.js +31 -31
  76. package/dist/tests/HIBPA.test.js +3 -3
  77. package/dist/tests/HICAZS.test.js +2 -2
  78. package/dist/tests/HIPINS.test.js +2 -2
  79. package/dist/tests/HIRMG.test.js +2 -2
  80. package/dist/tests/HITAB.test.js +5 -5
  81. package/dist/tests/HITANS.test.js +2 -2
  82. package/dist/tests/HIUPA.test.js +2 -2
  83. package/dist/tests/HIUPD.test.js +2 -2
  84. package/dist/tests/HIWPD.test.js +2 -2
  85. package/dist/tests/HKCAZ.test.js +3 -3
  86. package/dist/tests/HKIDN.test.js +2 -2
  87. package/dist/tests/HKSAL.test.js +3 -3
  88. package/dist/tests/HKTAN.test.js +4 -4
  89. package/dist/tests/HKWPD.test.js +2 -2
  90. package/dist/tests/HNSHK.test.js +2 -2
  91. package/dist/tests/HNVSK.test.js +2 -2
  92. package/dist/tests/camtParser.test.js +3 -3
  93. package/dist/tests/client.test.js +636 -22
  94. package/dist/tests/datatypes.test.js +1 -1
  95. package/dist/tests/dialog.test.js +21 -14
  96. package/dist/tests/message.test.js +4 -4
  97. package/dist/tests/mt535parser.test.js +1 -3
  98. package/dist/types/accountBalance.d.ts.map +1 -1
  99. package/dist/types/bankAccount.d.ts +2 -2
  100. package/dist/types/bankAccount.d.ts.map +1 -1
  101. package/dist/types/bankAnswer.d.ts.map +1 -1
  102. package/dist/types/bankTransaction.d.ts.map +1 -1
  103. package/dist/types/bankingInformation.d.ts +2 -2
  104. package/dist/types/bankingInformation.d.ts.map +1 -1
  105. package/dist/types/bpd.d.ts +3 -3
  106. package/dist/types/bpd.d.ts.map +1 -1
  107. package/dist/types/camtParser.d.ts +1 -1
  108. package/dist/types/camtParser.d.ts.map +1 -1
  109. package/dist/types/client.d.ts +5 -5
  110. package/dist/types/client.d.ts.map +1 -1
  111. package/dist/types/config.d.ts +4 -4
  112. package/dist/types/config.d.ts.map +1 -1
  113. package/dist/types/creditCardStatement.d.ts.map +1 -1
  114. package/dist/types/dataElements/AlphaNumeric.d.ts.map +1 -1
  115. package/dist/types/dataElements/Amount.d.ts.map +1 -1
  116. package/dist/types/dataElements/Binary.d.ts.map +1 -1
  117. package/dist/types/dataElements/Country.d.ts.map +1 -1
  118. package/dist/types/dataElements/Currency.d.ts.map +1 -1
  119. package/dist/types/dataElements/Dat.d.ts.map +1 -1
  120. package/dist/types/dataElements/DataElement.d.ts +3 -3
  121. package/dist/types/dataElements/DataElement.d.ts.map +1 -1
  122. package/dist/types/dataElements/Digits.d.ts.map +1 -1
  123. package/dist/types/dataElements/Float.d.ts.map +1 -1
  124. package/dist/types/dataElements/Identification.d.ts.map +1 -1
  125. package/dist/types/dataElements/Numeric.d.ts.map +1 -1
  126. package/dist/types/dataElements/Text.d.ts.map +1 -1
  127. package/dist/types/dataElements/Time.d.ts.map +1 -1
  128. package/dist/types/dataElements/YesNo.d.ts.map +1 -1
  129. package/dist/types/dataGroups/Account.d.ts.map +1 -1
  130. package/dist/types/dataGroups/Balance.d.ts +1 -1
  131. package/dist/types/dataGroups/Balance.d.ts.map +1 -1
  132. package/dist/types/dataGroups/BankIdentification.d.ts.map +1 -1
  133. package/dist/types/dataGroups/DataGroup.d.ts +3 -3
  134. package/dist/types/dataGroups/DataGroup.d.ts.map +1 -1
  135. package/dist/types/dataGroups/InternationalAccount.d.ts +1 -1
  136. package/dist/types/dataGroups/InternationalAccount.d.ts.map +1 -1
  137. package/dist/types/dataGroups/Money.d.ts.map +1 -1
  138. package/dist/types/dataGroups/RefMessage.d.ts.map +1 -1
  139. package/dist/types/dataGroups/SepaAccount.d.ts +1 -1
  140. package/dist/types/dataGroups/SepaAccount.d.ts.map +1 -1
  141. package/dist/types/dataGroups/TimeStamp.d.ts.map +1 -1
  142. package/dist/types/decoder.d.ts +2 -2
  143. package/dist/types/decoder.d.ts.map +1 -1
  144. package/dist/types/dialog.d.ts +2 -2
  145. package/dist/types/dialog.d.ts.map +1 -1
  146. package/dist/types/encoder.d.ts +2 -2
  147. package/dist/types/encoder.d.ts.map +1 -1
  148. package/dist/types/httpClient.d.ts +1 -1
  149. package/dist/types/httpClient.d.ts.map +1 -1
  150. package/dist/types/index.d.ts +12 -13
  151. package/dist/types/index.d.ts.map +1 -1
  152. package/dist/types/interactions/balanceInteraction.d.ts +5 -5
  153. package/dist/types/interactions/balanceInteraction.d.ts.map +1 -1
  154. package/dist/types/interactions/creditcardStatementInteraction.d.ts +6 -6
  155. package/dist/types/interactions/creditcardStatementInteraction.d.ts.map +1 -1
  156. package/dist/types/interactions/customerInteraction.d.ts +6 -6
  157. package/dist/types/interactions/customerInteraction.d.ts.map +1 -1
  158. package/dist/types/interactions/endDialogInteraction.d.ts +6 -6
  159. package/dist/types/interactions/endDialogInteraction.d.ts.map +1 -1
  160. package/dist/types/interactions/initDialogInteraction.d.ts +5 -5
  161. package/dist/types/interactions/initDialogInteraction.d.ts.map +1 -1
  162. package/dist/types/interactions/portfolioInteraction.d.ts +5 -5
  163. package/dist/types/interactions/portfolioInteraction.d.ts.map +1 -1
  164. package/dist/types/interactions/sepaAccountInteraction.d.ts +5 -5
  165. package/dist/types/interactions/sepaAccountInteraction.d.ts.map +1 -1
  166. package/dist/types/interactions/statementInteractionCAMT.d.ts +4 -4
  167. package/dist/types/interactions/statementInteractionCAMT.d.ts.map +1 -1
  168. package/dist/types/interactions/statementInteractionMT940.d.ts +4 -4
  169. package/dist/types/interactions/statementInteractionMT940.d.ts.map +1 -1
  170. package/dist/types/interactions/tanMediaInteraction.d.ts +4 -4
  171. package/dist/types/interactions/tanMediaInteraction.d.ts.map +1 -1
  172. package/dist/types/message.d.ts +3 -3
  173. package/dist/types/message.d.ts.map +1 -1
  174. package/dist/types/mt535parser.d.ts +0 -1
  175. package/dist/types/mt535parser.d.ts.map +1 -1
  176. package/dist/types/mt940parser.d.ts +1 -2
  177. package/dist/types/mt940parser.d.ts.map +1 -1
  178. package/dist/types/partedSegment.d.ts +1 -1
  179. package/dist/types/partedSegment.d.ts.map +1 -1
  180. package/dist/types/segment.d.ts +1 -1
  181. package/dist/types/segment.d.ts.map +1 -1
  182. package/dist/types/segmentDefinition.d.ts +2 -2
  183. package/dist/types/segmentDefinition.d.ts.map +1 -1
  184. package/dist/types/segmentHeader.d.ts.map +1 -1
  185. package/dist/types/segments/DIKKU.d.ts +4 -4
  186. package/dist/types/segments/DIKKU.d.ts.map +1 -1
  187. package/dist/types/segments/DKKKU.d.ts +3 -3
  188. package/dist/types/segments/DKKKU.d.ts.map +1 -1
  189. package/dist/types/segments/HIBPA.d.ts +5 -5
  190. package/dist/types/segments/HIBPA.d.ts.map +1 -1
  191. package/dist/types/segments/HICAZ.d.ts +2 -2
  192. package/dist/types/segments/HICAZ.d.ts.map +1 -1
  193. package/dist/types/segments/HICAZS.d.ts +1 -1
  194. package/dist/types/segments/HICAZS.d.ts.map +1 -1
  195. package/dist/types/segments/HIKAZ.d.ts +1 -1
  196. package/dist/types/segments/HIKAZ.d.ts.map +1 -1
  197. package/dist/types/segments/HIKAZS.d.ts +1 -1
  198. package/dist/types/segments/HIKAZS.d.ts.map +1 -1
  199. package/dist/types/segments/HIKIM.d.ts +2 -2
  200. package/dist/types/segments/HIKIM.d.ts.map +1 -1
  201. package/dist/types/segments/HIKOM.d.ts +3 -3
  202. package/dist/types/segments/HIKOM.d.ts.map +1 -1
  203. package/dist/types/segments/HIPINS.d.ts +1 -1
  204. package/dist/types/segments/HIPINS.d.ts.map +1 -1
  205. package/dist/types/segments/HIRMG.d.ts +1 -1
  206. package/dist/types/segments/HIRMG.d.ts.map +1 -1
  207. package/dist/types/segments/HIRMS.d.ts +2 -2
  208. package/dist/types/segments/HIRMS.d.ts.map +1 -1
  209. package/dist/types/segments/HISAL.d.ts +7 -7
  210. package/dist/types/segments/HISAL.d.ts.map +1 -1
  211. package/dist/types/segments/HISPA.d.ts +2 -2
  212. package/dist/types/segments/HISPA.d.ts.map +1 -1
  213. package/dist/types/segments/HISPAS.d.ts +2 -2
  214. package/dist/types/segments/HISPAS.d.ts.map +1 -1
  215. package/dist/types/segments/HISYN.d.ts +2 -2
  216. package/dist/types/segments/HISYN.d.ts.map +1 -1
  217. package/dist/types/segments/HITAB.d.ts +4 -4
  218. package/dist/types/segments/HITAB.d.ts.map +1 -1
  219. package/dist/types/segments/HITAN.d.ts +5 -5
  220. package/dist/types/segments/HITAN.d.ts.map +1 -1
  221. package/dist/types/segments/HITANS.d.ts +2 -2
  222. package/dist/types/segments/HITANS.d.ts.map +1 -1
  223. package/dist/types/segments/HIUPA.d.ts +3 -3
  224. package/dist/types/segments/HIUPA.d.ts.map +1 -1
  225. package/dist/types/segments/HIUPD.d.ts +6 -6
  226. package/dist/types/segments/HIUPD.d.ts.map +1 -1
  227. package/dist/types/segments/HIWPD.d.ts +1 -1
  228. package/dist/types/segments/HIWPD.d.ts.map +1 -1
  229. package/dist/types/segments/HKCAZ.d.ts +5 -5
  230. package/dist/types/segments/HKCAZ.d.ts.map +1 -1
  231. package/dist/types/segments/HKEND.d.ts +1 -1
  232. package/dist/types/segments/HKEND.d.ts.map +1 -1
  233. package/dist/types/segments/HKIDN.d.ts +3 -3
  234. package/dist/types/segments/HKIDN.d.ts.map +1 -1
  235. package/dist/types/segments/HKKAZ.d.ts +5 -5
  236. package/dist/types/segments/HKKAZ.d.ts.map +1 -1
  237. package/dist/types/segments/HKSAL.d.ts +6 -6
  238. package/dist/types/segments/HKSAL.d.ts.map +1 -1
  239. package/dist/types/segments/HKSPA.d.ts +3 -3
  240. package/dist/types/segments/HKSPA.d.ts.map +1 -1
  241. package/dist/types/segments/HKSYN.d.ts +2 -2
  242. package/dist/types/segments/HKSYN.d.ts.map +1 -1
  243. package/dist/types/segments/HKTAB.d.ts +3 -3
  244. package/dist/types/segments/HKTAB.d.ts.map +1 -1
  245. package/dist/types/segments/HKTAN.d.ts +6 -6
  246. package/dist/types/segments/HKTAN.d.ts.map +1 -1
  247. package/dist/types/segments/HKVVB.d.ts +3 -3
  248. package/dist/types/segments/HKVVB.d.ts.map +1 -1
  249. package/dist/types/segments/HKWPD.d.ts +2 -2
  250. package/dist/types/segments/HKWPD.d.ts.map +1 -1
  251. package/dist/types/segments/HNHBK.d.ts +3 -3
  252. package/dist/types/segments/HNHBK.d.ts.map +1 -1
  253. package/dist/types/segments/HNHBS.d.ts +1 -1
  254. package/dist/types/segments/HNHBS.d.ts.map +1 -1
  255. package/dist/types/segments/HNSHA.d.ts +3 -3
  256. package/dist/types/segments/HNSHA.d.ts.map +1 -1
  257. package/dist/types/segments/HNSHK.d.ts +4 -4
  258. package/dist/types/segments/HNSHK.d.ts.map +1 -1
  259. package/dist/types/segments/HNVSD.d.ts +2 -2
  260. package/dist/types/segments/HNVSD.d.ts.map +1 -1
  261. package/dist/types/segments/HNVSK.d.ts +4 -4
  262. package/dist/types/segments/HNVSK.d.ts.map +1 -1
  263. package/dist/types/segments/businessTransactionParameter.d.ts +2 -2
  264. package/dist/types/segments/businessTransactionParameter.d.ts.map +1 -1
  265. package/dist/types/segments/registry.d.ts +1 -1
  266. package/dist/types/segments/registry.d.ts.map +1 -1
  267. package/dist/types/tanMethod.d.ts +1 -1
  268. package/dist/types/tanMethod.d.ts.map +1 -1
  269. package/dist/types/unknownSegment.d.ts +1 -1
  270. package/dist/types/unknownSegment.d.ts.map +1 -1
  271. package/dist/types/upd.d.ts +2 -2
  272. package/dist/types/upd.d.ts.map +1 -1
  273. package/package.json +48 -47
@@ -75,7 +75,9 @@ export class CamtParser {
75
75
  }
76
76
  // Look for any object with BkToCstmrAcctRpt property
77
77
  for (const key in document) {
78
- if (document[key] && document[key].BkToCstmrAcctRpt) {
78
+ if (document[key] &&
79
+ typeof document[key] === 'object' &&
80
+ document[key]?.BkToCstmrAcctRpt) {
79
81
  return document[key];
80
82
  }
81
83
  }
@@ -130,12 +132,16 @@ export class CamtParser {
130
132
  }
131
133
  // Parse transactions
132
134
  const transactions = this.parseTransactions(report, reportNumber);
135
+ // At this point we should have both balances, otherwise throw an error
136
+ if (!openingBalance || !closingBalance) {
137
+ throw new CamtParsingError(`Unable to determine required balances for CAMT report ${reportNumber}`);
138
+ }
133
139
  return {
134
140
  account,
135
141
  number,
136
142
  transactionReference,
137
- openingBalance: openingBalance,
138
- closingBalance: closingBalance,
143
+ openingBalance,
144
+ closingBalance,
139
145
  availableBalance: balances.availableBalance,
140
146
  transactions,
141
147
  };
@@ -151,7 +157,7 @@ export class CamtParser {
151
157
  const pathParts = path.split('.');
152
158
  let current = obj;
153
159
  for (const part of pathParts) {
154
- if (current && typeof current === 'object' && current[part] !== undefined) {
160
+ if (current && typeof current === 'object' && current !== null && part in current) {
155
161
  current = current[part];
156
162
  }
157
163
  else {
@@ -161,7 +167,7 @@ export class CamtParser {
161
167
  if (typeof current === 'string' || typeof current === 'number') {
162
168
  return String(current);
163
169
  }
164
- if (current && typeof current === 'object' && current['#text'] !== undefined) {
170
+ if (current && typeof current === 'object' && current !== null && '#text' in current) {
165
171
  return String(current['#text']);
166
172
  }
167
173
  return undefined;
@@ -180,7 +186,10 @@ export class CamtParser {
180
186
  for (const balanceObj of balanceArray) {
181
187
  const typeCode = this.getValueFromPath(balanceObj, 'Tp.CdOrPrtry.Cd');
182
188
  // Extract amount and currency
183
- const currency = balanceObj.Amt?.['@Ccy'] || 'EUR';
189
+ let currency = 'EUR';
190
+ if (balanceObj.Amt && typeof balanceObj.Amt === 'object' && '@Ccy' in balanceObj.Amt) {
191
+ currency = balanceObj.Amt['@Ccy'] || 'EUR';
192
+ }
184
193
  const value = parseFloat(this.getValueFromPath(balanceObj, 'Amt') || '0');
185
194
  const creditDebitInd = this.getValueFromPath(balanceObj, 'CdtDbtInd');
186
195
  const finalValue = creditDebitInd === 'DBIT' ? -value : value;
@@ -237,7 +246,7 @@ export class CamtParser {
237
246
  const entryArray = Array.isArray(entries) ? entries : [entries];
238
247
  for (let i = 0; i < entryArray.length; i++) {
239
248
  try {
240
- const transaction = this.parseTransaction(entryArray[i], reportNumber, i + 1);
249
+ const transaction = this.parseTransaction(entryArray[i]);
241
250
  if (transaction) {
242
251
  transactions.push(transaction);
243
252
  }
@@ -248,7 +257,7 @@ export class CamtParser {
248
257
  }
249
258
  return transactions;
250
259
  }
251
- parseTransaction(entry, reportNumber, transactionNumber) {
260
+ parseTransaction(entry) {
252
261
  try {
253
262
  // Extract amount and credit/debit indicator
254
263
  const amountValue = parseFloat(this.getValueFromPath(entry, 'Amt') || '0');
@@ -381,7 +390,7 @@ export class CamtParser {
381
390
  parseDate(dateStr) {
382
391
  // Parse ISO date format (YYYY-MM-DD)
383
392
  if (dateStr.length === 10 && dateStr.includes('-')) {
384
- return new Date(dateStr + 'T12:00:00'); // Set time to noon to avoid timezone issues
393
+ return new Date(`${dateStr}T12:00:00`); // Set time to noon to avoid timezone issues
385
394
  }
386
395
  // Parse CAMT date format (YYYYMMDD)
387
396
  if (dateStr.length === 8) {
package/dist/client.js CHANGED
@@ -1,16 +1,16 @@
1
+ import { FinTSConfig } from './config.js';
1
2
  import { Dialog } from './dialog.js';
2
- import { StatementInteractionMT940 } from './interactions/statementInteractionMT940.js';
3
+ import { BalanceInteraction, } from './interactions/balanceInteraction.js';
4
+ import { CreditCardStatementInteraction } from './interactions/creditcardStatementInteraction.js';
5
+ import { PortfolioInteraction, } from './interactions/portfolioInteraction.js';
3
6
  import { StatementInteractionCAMT } from './interactions/statementInteractionCAMT.js';
4
- import { BalanceInteraction } from './interactions/balanceInteraction.js';
5
- import { PortfolioInteraction } from './interactions/portfolioInteraction.js';
6
- import { FinTSConfig } from './config.js';
7
- import { HKSAL } from './segments/HKSAL.js';
8
- import { HKKAZ } from './segments/HKKAZ.js';
9
- import { HKCAZ } from './segments/HKCAZ.js';
10
- import { HKWPD } from './segments/HKWPD.js';
7
+ import { StatementInteractionMT940 } from './interactions/statementInteractionMT940.js';
11
8
  import { DKKKU } from './segments/DKKKU.js';
12
- import { CreditCardStatementInteraction } from './interactions/creditcardStatementInteraction.js';
9
+ import { HKCAZ } from './segments/HKCAZ.js';
13
10
  import { HKIDN } from './segments/HKIDN.js';
11
+ import { HKKAZ } from './segments/HKKAZ.js';
12
+ import { HKSAL } from './segments/HKSAL.js';
13
+ import { HKWPD } from './segments/HKWPD.js';
14
14
  /**
15
15
  * A client to communicate with a bank over the FinTS protocol
16
16
  */
@@ -36,8 +36,7 @@ export class FinTSClient {
36
36
  * @returns the selected TAN method
37
37
  */
38
38
  selectTanMethod(tanMethodId) {
39
- this.config.selectTanMethod(tanMethodId);
40
- return this.config.selectedTanMethod;
39
+ return this.config.selectTanMethod(tanMethodId);
41
40
  }
42
41
  /**
43
42
  * Selects a TAN media by its name
@@ -62,8 +61,7 @@ export class FinTSClient {
62
61
  * @returns the synchronization response
63
62
  */
64
63
  async synchronizeWithTan(tanReference, tan) {
65
- const responses = await this.continueCustomerInteractionWithTan(tanReference, tan);
66
- return responses.get(HKIDN.Id);
64
+ return await this.continueCustomerInteractionWithTan([HKIDN.Id], tanReference, tan);
67
65
  }
68
66
  /**
69
67
  * Checks if the bank supports fetching an account balance in general or for the given account number when provided
@@ -81,8 +79,8 @@ export class FinTSClient {
81
79
  * @returns the account balance response
82
80
  */
83
81
  async getAccountBalance(accountNumber) {
84
- const responses = await this.startCustomerOrderInteraction(new BalanceInteraction(accountNumber));
85
- return responses.get(HKSAL.Id);
82
+ const response = await this.startCustomerOrderInteraction(new BalanceInteraction(accountNumber));
83
+ return response;
86
84
  }
87
85
  /**
88
86
  * Continues the account balance fetching when a TAN is required
@@ -91,8 +89,7 @@ export class FinTSClient {
91
89
  * @returns the account balance response
92
90
  */
93
91
  async getAccountBalanceWithTan(tanReference, tan) {
94
- const responses = await this.continueCustomerInteractionWithTan(tanReference, tan);
95
- return responses.get(HKSAL.Id);
92
+ return (await this.continueCustomerInteractionWithTan([HKSAL.Id], tanReference, tan));
96
93
  }
97
94
  /**
98
95
  * Checks if the bank supports fetching account statements in general or for the given account number when provided
@@ -107,7 +104,7 @@ export class FinTSClient {
107
104
  }
108
105
  else {
109
106
  // Check if either CAMT or MT940 is supported by the bank
110
- return this.config.isTransactionSupported(HKCAZ.Id) || this.config.isTransactionSupported(HKKAZ.Id);
107
+ return (this.config.isTransactionSupported(HKCAZ.Id) || this.config.isTransactionSupported(HKKAZ.Id));
111
108
  }
112
109
  }
113
110
  /**
@@ -128,12 +125,10 @@ export class FinTSClient {
128
125
  // Choose format based on support and preference
129
126
  const useCAMT = (preferCamt && camtSupported) || (!mt940Supported && camtSupported);
130
127
  if (useCAMT) {
131
- const responses = await this.startCustomerOrderInteraction(new StatementInteractionCAMT(accountNumber, from, to));
132
- return responses.get(HKCAZ.Id);
128
+ return (await this.startCustomerOrderInteraction(new StatementInteractionCAMT(accountNumber, from, to)));
133
129
  }
134
130
  else {
135
- const responses = await this.startCustomerOrderInteraction(new StatementInteractionMT940(accountNumber, from, to));
136
- return responses.get(HKKAZ.Id);
131
+ return (await this.startCustomerOrderInteraction(new StatementInteractionMT940(accountNumber, from, to)));
137
132
  }
138
133
  }
139
134
  /**
@@ -143,8 +138,7 @@ export class FinTSClient {
143
138
  * @returns an account statements response containing an array of statements
144
139
  */
145
140
  async getAccountStatementsWithTan(tanReference, tan) {
146
- const responses = await this.continueCustomerInteractionWithTan(tanReference, tan);
147
- return responses.get(HKKAZ.Id);
141
+ return (await this.continueCustomerInteractionWithTan([HKCAZ.Id, HKKAZ.Id], tanReference, tan));
148
142
  }
149
143
  /**
150
144
  * Checks if the bank supports fetching portfolio information in general or for the given account number when provided
@@ -165,8 +159,7 @@ export class FinTSClient {
165
159
  * @returns a portfolio response containing holdings and total value
166
160
  */
167
161
  async getPortfolio(accountNumber, currency, priceQuality, maxEntries) {
168
- const responses = await this.startCustomerOrderInteraction(new PortfolioInteraction(accountNumber, currency, priceQuality, maxEntries));
169
- return responses.get(HKWPD.Id);
162
+ return (await this.startCustomerOrderInteraction(new PortfolioInteraction(accountNumber, currency, priceQuality, maxEntries)));
170
163
  }
171
164
  /**
172
165
  * Continues the portfolio fetching when a TAN is required
@@ -176,8 +169,7 @@ export class FinTSClient {
176
169
  * @returns a portfolio response containing holdings and total value
177
170
  */
178
171
  async getPortfolioWithTan(tanReference, tan) {
179
- const responses = await this.continueCustomerInteractionWithTan(tanReference, tan);
180
- return responses.get(HKWPD.Id);
172
+ return (await this.continueCustomerInteractionWithTan([HKWPD.Id], tanReference, tan));
181
173
  }
182
174
  /**
183
175
  * Checks if the bank supports fetching credit card statements in general or for the given account number
@@ -198,8 +190,7 @@ export class FinTSClient {
198
190
  * @returns an account statements response containing an array of statements
199
191
  */
200
192
  async getCreditCardStatements(accountNumber, from) {
201
- const responses = await this.startCustomerOrderInteraction(new CreditCardStatementInteraction(accountNumber, from));
202
- return responses.get(DKKKU.Id);
193
+ return (await this.startCustomerOrderInteraction(new CreditCardStatementInteraction(accountNumber, from)));
203
194
  }
204
195
  /**
205
196
  * Continues the credit card statements fetching when a TAN is required
@@ -208,18 +199,43 @@ export class FinTSClient {
208
199
  * @returns a credit card statements response containing an array of statements
209
200
  */
210
201
  async getCreditCardStatementsWithTan(tanReference, tan) {
211
- const responses = await this.continueCustomerInteractionWithTan(tanReference, tan);
212
- return responses.get(DKKKU.Id);
202
+ return (await this.continueCustomerInteractionWithTan([DKKKU.Id], tanReference, tan));
213
203
  }
214
204
  async startCustomerOrderInteraction(interaction) {
215
205
  this.currentDialog = new Dialog(this.config, false);
216
206
  this.currentDialog.addCustomerInteraction(interaction);
217
- return await this.currentDialog.start();
207
+ const responses = await this.currentDialog.start();
208
+ const response = responses.get(interaction.segId);
209
+ if (response) {
210
+ return response;
211
+ }
212
+ else {
213
+ const lastResponse = [...responses.values()].at(-1);
214
+ if (lastResponse) {
215
+ return lastResponse;
216
+ }
217
+ else {
218
+ throw new Error(`No response received for customer interaction with segment ID '${interaction.segId}'`);
219
+ }
220
+ }
218
221
  }
219
- async continueCustomerInteractionWithTan(tanReference, tan) {
222
+ async continueCustomerInteractionWithTan(segIds, tanReference, tan) {
220
223
  if (!this.currentDialog) {
221
224
  throw new Error('no customer dialog was started which can continue');
222
225
  }
223
- return await this.currentDialog.continue(tanReference, tan);
226
+ const responses = await this.currentDialog.continue(tanReference, tan);
227
+ for (const segId of segIds) {
228
+ const response = responses.get(segId);
229
+ if (response) {
230
+ return response;
231
+ }
232
+ }
233
+ const lastResponse = [...responses.values()].at(-1);
234
+ if (lastResponse) {
235
+ return lastResponse;
236
+ }
237
+ else {
238
+ throw new Error(`No response received for customer interaction with segment IDs '${segIds.join(', ')}'`);
239
+ }
224
240
  }
225
241
  }
package/dist/config.js CHANGED
@@ -89,19 +89,19 @@ export class FinTSConfig {
89
89
  * The FinTS URL of the bank
90
90
  */
91
91
  get bankingUrl() {
92
- return this.bankingInformation.bpd?.url ?? this.url;
92
+ return this.bankingInformation.bpd?.url ?? this.url ?? '';
93
93
  }
94
94
  /**
95
95
  * The country code of the bank
96
96
  */
97
97
  get countryCode() {
98
- return this.bankingInformation.bpd?.countryCode ?? this.country;
98
+ return this.bankingInformation.bpd?.countryCode ?? this.country ?? 280;
99
99
  }
100
100
  /**
101
101
  * The bank ID (BLZ)
102
102
  */
103
103
  get bankId() {
104
- return this.bankingInformation.bpd?.bankId ?? this.bankIdentification;
104
+ return this.bankingInformation.bpd?.bankId ?? this.bankIdentification ?? '';
105
105
  }
106
106
  /**
107
107
  * A list of all available TAN methods for the user
@@ -114,10 +114,12 @@ export class FinTSConfig {
114
114
  * @param tanMethodId The ID of the TAN method to select, corresponding to an ID in availableTanMethods
115
115
  */
116
116
  selectTanMethod(tanMethodId) {
117
- if (!this.availableTanMethods.find((method) => method.id === tanMethodId)) {
117
+ const tanMethod = this.availableTanMethods.find((method) => method.id === tanMethodId);
118
+ if (!tanMethod) {
118
119
  throw new Error(`TAN Method '${tanMethodId}' is not supported`);
119
120
  }
120
121
  this.tanMethodId = tanMethodId;
122
+ return tanMethod;
121
123
  }
122
124
  /**
123
125
  * Selects a TAN media by its name for the user
@@ -143,7 +145,8 @@ export class FinTSConfig {
143
145
  * @param transId The transaction ID
144
146
  */
145
147
  isTransactionSupported(transId) {
146
- return this.bankingInformation.bpd?.allowedTransactions.find((t) => t.transId === transId) !== undefined;
148
+ return (this.bankingInformation.bpd?.allowedTransactions.find((t) => t.transId === transId) !==
149
+ undefined);
147
150
  }
148
151
  /**
149
152
  * Checks if a transaction is supported for a specific account
@@ -163,7 +166,8 @@ export class FinTSConfig {
163
166
  if (!definition) {
164
167
  throw new Error(`segment definition for ${transId} not registered`);
165
168
  }
166
- const allowedVersions = this.bankingInformation.bpd?.allowedTransactions.find((t) => t.transId === transId)?.versions ?? [];
169
+ const allowedVersions = this.bankingInformation.bpd?.allowedTransactions.find((t) => t.transId === transId)
170
+ ?.versions ?? [];
167
171
  const maxSupportedversion = allowedVersions.sort().findLast((version) => version <= definition.version) ?? undefined;
168
172
  return maxSupportedversion;
169
173
  }
@@ -1,5 +1,5 @@
1
- import { DataElement } from './DataElement.js';
2
1
  import { finTsDecode, finTsEncode } from '../format.js';
2
+ import { DataElement } from './DataElement.js';
3
3
  export class AlphaNumeric extends DataElement {
4
4
  maxLength;
5
5
  constructor(name, minCount = 0, maxCount = 1, maxLength, minVersion, maxVersion) {
@@ -21,7 +21,8 @@ export class DataElement {
21
21
  return this.isInVersion(version) ? 1 : 0;
22
22
  }
23
23
  isInVersion(version) {
24
- return (!this.minVersion || version >= this.minVersion) && (!this.maxVersion || version <= this.maxVersion);
24
+ return ((!this.minVersion || version >= this.minVersion) &&
25
+ (!this.maxVersion || version <= this.maxVersion));
25
26
  }
26
27
  toString(value) {
27
28
  if (value !== undefined && value !== null && value !== '') {
@@ -18,6 +18,6 @@ export class Digits extends DataElement {
18
18
  return value.toString().padStart(this.digits, '0');
19
19
  }
20
20
  decode(text) {
21
- return Number.parseInt(text);
21
+ return Number.parseInt(text, 10);
22
22
  }
23
23
  }
@@ -13,7 +13,7 @@ export class Float extends DataElement {
13
13
  throw Error(`the Float value '${this.name}' must not exceed its maximum length`);
14
14
  }
15
15
  const text = value.toString().replace('.', ',');
16
- return text.indexOf(',') >= 0 ? text : text + ',';
16
+ return text.indexOf(',') >= 0 ? text : `${text},`;
17
17
  }
18
18
  decode(text) {
19
19
  return Number.parseFloat(text.replace(',', '.'));
@@ -18,9 +18,9 @@ export class Numeric extends DataElement {
18
18
  return value.toString();
19
19
  }
20
20
  decode(text) {
21
- return Number.parseInt(text);
21
+ return Number.parseInt(text, 10);
22
22
  }
23
23
  static decode(text) {
24
- return Number.parseInt(text);
24
+ return Number.parseInt(text, 10);
25
25
  }
26
26
  }
@@ -1,5 +1,5 @@
1
- import { DataElement } from './DataElement.js';
2
1
  import { finTsDecode, finTsEncode } from '../format.js';
2
+ import { DataElement } from './DataElement.js';
3
3
  export class Text extends DataElement {
4
4
  maxLength;
5
5
  constructor(name, minCount = 0, maxCount = 1, maxLength, minVersion, maxVersion) {
@@ -1,6 +1,6 @@
1
- import { DataGroup } from './DataGroup.js';
2
1
  import { Identification } from '../dataElements/Identification.js';
3
2
  import { BankIdentification } from './BankIdentification.js';
3
+ import { DataGroup } from './DataGroup.js';
4
4
  export class AccountGroup extends DataGroup {
5
5
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
6
6
  super(name, [
@@ -1,6 +1,6 @@
1
- import { Time } from '../dataElements/Time.js';
2
- import { Dat } from '../dataElements/Dat.js';
3
1
  import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
2
+ import { Dat } from '../dataElements/Dat.js';
3
+ import { Time } from '../dataElements/Time.js';
4
4
  import { DataGroup } from './DataGroup.js';
5
5
  import { MoneyGroup } from './Money.js';
6
6
  export class BalanceGroup extends DataGroup {
@@ -1,6 +1,6 @@
1
1
  import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
2
- import { DataGroup } from './DataGroup.js';
3
2
  import { Country } from '../dataElements/Country.js';
3
+ import { DataGroup } from './DataGroup.js';
4
4
  export class BankIdentification extends DataGroup {
5
5
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
6
6
  super(name, [new Country('country', 1, 1), new AlphaNumeric('bankId', 1, 1, 30)], minCount, maxCount, minVersion, maxVersion);
@@ -21,7 +21,10 @@ export class DataGroup extends DataElement {
21
21
  throw new Error('version is required for encoding an element group');
22
22
  }
23
23
  const isSingleArray = this.elements.length === 1 && this.elements[0].maxCount > 1;
24
- return encodeElements(isSingleArray ? [values] : values, this.elements, ':', version, [...context, this.name]);
24
+ return encodeElements(isSingleArray ? [values] : values, this.elements, ':', version, [
25
+ ...context,
26
+ this.name,
27
+ ]);
25
28
  }
26
29
  decode(text, version) {
27
30
  if (!text.replaceAll(':', '')) {
@@ -36,18 +39,22 @@ export class DataGroup extends DataElement {
36
39
  if (!values) {
37
40
  return '';
38
41
  }
39
- let texts = this.elements.map((element) => {
42
+ const texts = this.elements.map((element) => {
40
43
  if (element.maxCount > 1) {
41
- if (this.elements.length === 1) {
44
+ if (this.elements.length === 1 && Array.isArray(values)) {
42
45
  return values.map((value) => element.toString(value)).join('; ');
43
46
  }
44
- else {
45
- return values[element.name]?.map((value) => element.toString(value)).join('; ') ?? '';
47
+ else if (!Array.isArray(values)) {
48
+ const currentValue = values[element.name];
49
+ return Array.isArray(currentValue)
50
+ ? currentValue.map((value) => element.toString(value)).join('; ')
51
+ : element.toString(currentValue);
46
52
  }
47
53
  }
48
- else {
54
+ else if (!Array.isArray(values)) {
49
55
  return element.toString(values[element.name]);
50
56
  }
57
+ return element.toString(undefined);
51
58
  });
52
59
  return `[${texts.filter((text) => !!text).join(', ')}]`;
53
60
  }
@@ -1,7 +1,7 @@
1
1
  import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
2
- import { DataGroup } from './DataGroup.js';
3
2
  import { Identification } from '../dataElements/Identification.js';
4
3
  import { BankIdentification } from './BankIdentification.js';
4
+ import { DataGroup } from './DataGroup.js';
5
5
  export class InternationalAccountGroup extends DataGroup {
6
6
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
7
7
  super(name, [
@@ -1,6 +1,6 @@
1
- import { DataGroup } from './DataGroup.js';
2
1
  import { Amount } from '../dataElements/Amount.js';
3
2
  import { Currency } from '../dataElements/Currency.js';
3
+ import { DataGroup } from './DataGroup.js';
4
4
  export class MoneyGroup extends DataGroup {
5
5
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
6
6
  super(name, [new Amount('value', 1, 1), new Currency('currency', 1, 1)], minCount, maxCount, minVersion, maxVersion);
@@ -1,6 +1,6 @@
1
+ import { Identification } from '../dataElements/Identification.js';
1
2
  import { Numeric } from '../dataElements/Numeric.js';
2
3
  import { DataGroup } from './DataGroup.js';
3
- import { Identification } from '../dataElements/Identification.js';
4
4
  export class RefMessageGroup extends DataGroup {
5
5
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
6
6
  super(name, [new Identification('dialogId', 1, 1), new Numeric('msgNr', 1, 1, 4)], minCount, maxCount, minVersion, maxVersion);
@@ -1,8 +1,8 @@
1
1
  import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
2
- import { DataGroup } from './DataGroup.js';
3
2
  import { Identification } from '../dataElements/Identification.js';
4
- import { BankIdentification } from './BankIdentification.js';
5
3
  import { YesNo } from '../dataElements/YesNo.js';
4
+ import { BankIdentification } from './BankIdentification.js';
5
+ import { DataGroup } from './DataGroup.js';
6
6
  export class SepaAccountGroup extends DataGroup {
7
7
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
8
8
  super(name, [
@@ -1,6 +1,6 @@
1
- import { YesNo } from '../dataElements/YesNo.js';
2
- import { Numeric } from '../dataElements/Numeric.js';
3
1
  import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
2
+ import { Numeric } from '../dataElements/Numeric.js';
3
+ import { YesNo } from '../dataElements/YesNo.js';
4
4
  import { DataGroup } from './DataGroup.js';
5
5
  export class SepaAccountParametersGroup extends DataGroup {
6
6
  constructor(name, minCount = 1, maxCount = 1, minVersion, maxVersion) {
@@ -1,5 +1,5 @@
1
- import { Time } from '../dataElements/Time.js';
2
1
  import { Dat } from '../dataElements/Dat.js';
2
+ import { Time } from '../dataElements/Time.js';
3
3
  import { DataGroup } from './DataGroup.js';
4
4
  export class TimeStampGroup extends DataGroup {
5
5
  constructor(name, minCount = 0, maxCount = 1, minVersion, maxVersion) {
package/dist/decoder.js CHANGED
@@ -10,7 +10,9 @@ export function decodeElements(text, elements, separator, version, context) {
10
10
  if (element.isInVersion(version)) {
11
11
  let textValue;
12
12
  if (separator === ':') {
13
- textValue = textValues.slice(valueIndex, valueIndex + element.maxValueCount(version)).join(':');
13
+ textValue = textValues
14
+ .slice(valueIndex, valueIndex + element.maxValueCount(version))
15
+ .join(':');
14
16
  valueIndex += element.maxValueCount(version);
15
17
  }
16
18
  else {
@@ -27,13 +29,14 @@ export function decodeElements(text, elements, separator, version, context) {
27
29
  else {
28
30
  value = element.decode(textValue, version);
29
31
  }
30
- if (isResultArray) {
32
+ if (Array.isArray(result)) {
31
33
  if (element.maxCount > 1) {
32
34
  if (elements.length === 1) {
33
35
  result = [...result, value];
34
36
  }
35
37
  else {
36
- result[elementIndex] = result[elementIndex] ? [...result[elementIndex], value] : [value];
38
+ const currentValue = result[elementIndex];
39
+ result[elementIndex] = Array.isArray(currentValue) ? [...currentValue, value] : [value];
37
40
  }
38
41
  }
39
42
  else {
@@ -42,7 +45,8 @@ export function decodeElements(text, elements, separator, version, context) {
42
45
  }
43
46
  else {
44
47
  if (element.maxCount > 1) {
45
- result[element.name] = result[element.name] ? [...result[element.name], value] : [value];
48
+ const currentValue = result[element.name];
49
+ result[element.name] = Array.isArray(currentValue) ? [...currentValue, value] : [value];
46
50
  }
47
51
  else {
48
52
  result[element.name] = value;
@@ -51,7 +55,9 @@ export function decodeElements(text, elements, separator, version, context) {
51
55
  }
52
56
  elementCount++;
53
57
  if (valueIndex >= textValues.length) {
54
- if (elements.slice(elementIndex + 1).some((element) => element.isInVersion(version) && element.minCount > 0)) {
58
+ if (elements
59
+ .slice(elementIndex + 1)
60
+ .some((element) => element.isInVersion(version) && element.minCount > 0)) {
55
61
  throw new Error(`Not all mandatory values are present in '${context}', expected a value for element '${elements[elementIndex + 1].name}'`);
56
62
  }
57
63
  else {
@@ -72,7 +78,7 @@ export function splitBySeparator(text, separator) {
72
78
  const char = text[index];
73
79
  if (char === '@' && !isEscaped(text, index)) {
74
80
  const next = text.indexOf('@', index + 1);
75
- const size = Number.parseInt(text.slice(index + 1, next));
81
+ const size = Number.parseInt(text.slice(index + 1, next), 10);
76
82
  if (size) {
77
83
  index = next + size;
78
84
  }