lib-fints 1.4.1 → 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 +31 -20
  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 +15 -15
  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 +11 -11
  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
@@ -105,7 +104,7 @@ export class FinTSClient {
105
104
  }
106
105
  else {
107
106
  // Check if either CAMT or MT940 is supported by the bank
108
- return this.config.isTransactionSupported(HKCAZ.Id) || this.config.isTransactionSupported(HKKAZ.Id);
107
+ return (this.config.isTransactionSupported(HKCAZ.Id) || this.config.isTransactionSupported(HKKAZ.Id));
109
108
  }
110
109
  }
111
110
  /**
@@ -163,12 +162,12 @@ export class FinTSClient {
163
162
  return (await this.startCustomerOrderInteraction(new PortfolioInteraction(accountNumber, currency, priceQuality, maxEntries)));
164
163
  }
165
164
  /**
166
- * Continues the portfolio fetching when a TAN is required
167
- * @param tanReference The TAN reference provided in the first call's response
168
-
169
- * @param tan The TAN entered by the user, can be omitted if a decoupled TAN method is used
170
- * @returns a portfolio response containing holdings and total value
171
- */
165
+ * Continues the portfolio fetching when a TAN is required
166
+ * @param tanReference The TAN reference provided in the first call's response
167
+
168
+ * @param tan The TAN entered by the user, can be omitted if a decoupled TAN method is used
169
+ * @returns a portfolio response containing holdings and total value
170
+ */
172
171
  async getPortfolioWithTan(tanReference, tan) {
173
172
  return (await this.continueCustomerInteractionWithTan([HKWPD.Id], tanReference, tan));
174
173
  }
@@ -211,7 +210,13 @@ export class FinTSClient {
211
210
  return response;
212
211
  }
213
212
  else {
214
- return [...responses.values()].at(-1);
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
+ }
215
220
  }
216
221
  }
217
222
  async continueCustomerInteractionWithTan(segIds, tanReference, tan) {
@@ -225,6 +230,12 @@ export class FinTSClient {
225
230
  return response;
226
231
  }
227
232
  }
228
- return [...responses.values()].at(-1);
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
+ }
229
240
  }
230
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
  }
package/dist/dialog.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { TanMediaRequirement, TanProcess } from './codes.js';
2
2
  import { HttpClient } from './httpClient.js';
3
+ import { CustomerOrderInteraction, } from './interactions/customerInteraction.js';
4
+ import { EndDialogInteraction } from './interactions/endDialogInteraction.js';
5
+ import { InitDialogInteraction } from './interactions/initDialogInteraction.js';
3
6
  import { CustomerMessage, CustomerOrderMessage } from './message.js';
4
- import { HKIDN } from './segments/HKIDN.js';
7
+ import { PARTED } from './partedSegment.js';
8
+ import { decode } from './segment.js';
9
+ import { HKEND } from './segments/HKEND.js';
5
10
  import { HKTAN } from './segments/HKTAN.js';
6
11
  import { HNHBK } from './segments/HNHBK.js';
7
- import { decode } from './segment.js';
8
- import { PARTED } from './partedSegment.js';
9
- import { CustomerOrderInteraction } from './interactions/customerInteraction.js';
10
- import { InitDialogInteraction } from './interactions/initDialogInteraction.js';
11
- import { EndDialogInteraction } from './interactions/endDialogInteraction.js';
12
12
  export class Dialog {
13
13
  config;
14
14
  dialogId = '0';
@@ -125,22 +125,24 @@ export class Dialog {
125
125
  ? new CustomerOrderMessage(this.currentInteraction.segId, this.currentInteraction.responseSegId, this.dialogId, this.lastMessageNumber)
126
126
  : new CustomerMessage(this.dialogId, this.lastMessageNumber);
127
127
  const tanMethod = this.config.selectedTanMethod;
128
- let isScaSupported = tanMethod && tanMethod.version >= 6;
129
- let isTanMethodNeeded = isScaSupported;
128
+ const isScaSupported = tanMethod && tanMethod.version >= 6;
129
+ let isTanMethodNeeded = isScaSupported && this.currentInteraction.segId !== HKEND.Id;
130
130
  if (isCustomerOrder) {
131
131
  const bankTransaction = this.config.bankingInformation.bpd?.allowedTransactions.find((t) => t.transId === this.currentInteraction.segId);
132
- isTanMethodNeeded = isScaSupported && bankTransaction?.tanRequired;
132
+ isTanMethodNeeded = isTanMethodNeeded && bankTransaction?.tanRequired;
133
133
  }
134
134
  if (this.config.userId && this.config.pin) {
135
135
  message.sign(this.config.countryCode, this.config.bankId, this.config.userId, this.config.pin, this.config.bankingInformation.systemId, isScaSupported ? this.config.tanMethodId : undefined);
136
136
  }
137
137
  const segments = this.currentInteraction.getSegments(this.config);
138
- segments.forEach((segment) => message.addSegment(segment));
138
+ segments.forEach((segment) => {
139
+ message.addSegment(segment);
140
+ });
139
141
  if (this.config.userId && this.config.pin && isTanMethodNeeded) {
140
142
  const hktan = {
141
- header: { segId: HKTAN.Id, segNr: 0, version: tanMethod.version },
143
+ header: { segId: HKTAN.Id, segNr: 0, version: tanMethod?.version ?? 0 },
142
144
  tanProcess: TanProcess.Process4,
143
- segId: HKIDN.Id,
145
+ segId: this.currentInteraction.segId,
144
146
  };
145
147
  message.addSegment(hktan);
146
148
  }
@@ -150,16 +152,19 @@ export class Dialog {
150
152
  this.lastMessageNumber++;
151
153
  const message = new CustomerMessage(this.dialogId, this.lastMessageNumber);
152
154
  if (this.config.userId && this.config.pin) {
153
- message.sign(this.config.countryCode, this.config.bankId, this.config.userId, this.config.pin, this.config.bankingInformation.systemId, this.config.tanMethodId, tan);
155
+ message.sign(this.config.countryCode, this.config.bankId, this.config.userId, this.config.pin, this.config.bankingInformation?.systemId, this.config.tanMethodId, tan);
154
156
  }
155
157
  if (this.config.userId && this.config.pin && this.config.tanMethodId) {
156
158
  const hktan = {
157
- header: { segId: HKTAN.Id, segNr: 0, version: this.config.selectedTanMethod.version },
158
- tanProcess: this.config.selectedTanMethod?.isDecoupled ? TanProcess.Status : TanProcess.Process2,
159
+ header: { segId: HKTAN.Id, segNr: 0, version: this.config.selectedTanMethod?.version ?? 0 },
160
+ tanProcess: this.config.selectedTanMethod?.isDecoupled
161
+ ? TanProcess.Status
162
+ : TanProcess.Process2,
159
163
  segId: this.currentInteraction.segId,
160
164
  orderRef: tanOrderReference,
161
165
  nextTan: false,
162
- tanMedia: this.config.selectedTanMethod.tanMediaRequirement >= TanMediaRequirement.Optional
166
+ tanMedia: (this.config.selectedTanMethod?.tanMediaRequirement ??
167
+ TanMediaRequirement.NotAllowed >= TanMediaRequirement.Optional)
163
168
  ? this.config.tanMediaName
164
169
  : undefined,
165
170
  };
@@ -176,13 +181,22 @@ export class Dialog {
176
181
  if (!segmentWithContinuation) {
177
182
  throw new Error(`Response contains segment with further information, but corresponding segment could not be found or is not specified`);
178
183
  }
179
- segmentWithContinuation.continuationMark = answers.find((a) => a.code === 3040).params[0];
180
- message.findSegment(HNHBK.Id).msgNr = ++this.lastMessageNumber;
184
+ const answer = answers.find((a) => a.code === 3040);
185
+ if (!answer || !answer.params || answer.params.length === 0) {
186
+ throw new Error('Expected bank answer to contain continuation mark parameters (code 3040)');
187
+ }
188
+ segmentWithContinuation.continuationMark = answer.params[0];
189
+ const hnhbkSegment = message.findSegment(HNHBK.Id);
190
+ if (!hnhbkSegment) {
191
+ throw new Error('HNHBK segment not found in message');
192
+ }
193
+ hnhbkSegment.msgNr = ++this.lastMessageNumber;
181
194
  const nextResponseMessage = await this.httpClient.sendMessage(message);
182
195
  const nextPartedSegment = nextResponseMessage.findSegment(PARTED.Id);
183
196
  if (nextPartedSegment) {
184
197
  nextPartedSegment.rawData =
185
- partedSegment.rawData + nextPartedSegment.rawData.slice(nextPartedSegment.rawData.indexOf('+') + 1);
198
+ partedSegment.rawData +
199
+ nextPartedSegment.rawData.slice(nextPartedSegment.rawData.indexOf('+') + 1);
186
200
  partedSegment = nextPartedSegment;
187
201
  }
188
202
  responseMessage = nextResponseMessage;
package/dist/encoder.js CHANGED
@@ -1,6 +1,8 @@
1
1
  export function encodeElements(values, elements, separator, version, context) {
2
2
  const isArray = Array.isArray(values);
3
- if (!values || (isArray && values.length === 0) || (!isArray && Object.keys(values).length === 0)) {
3
+ if (!values ||
4
+ (isArray && values.length === 0) ||
5
+ (!isArray && Object.keys(values).length === 0)) {
4
6
  if (context.length >= 3) {
5
7
  return separator.repeat(elements.reduce((sum, element) => sum + element.maxValueCount(version), 0) - 1);
6
8
  }
@@ -9,7 +11,7 @@ export function encodeElements(values, elements, separator, version, context) {
9
11
  if (isArray && values.length !== elements.length) {
10
12
  throw new Error(`Values to encode don't match number of elements (${values.length} <> ${elements.length}) when encoding '${context.join('->')}'`);
11
13
  }
12
- let textValues = [];
14
+ const textValues = [];
13
15
  let elementIndex = 0;
14
16
  while (elementIndex < elements.length) {
15
17
  const element = elements[elementIndex];
@@ -24,7 +26,12 @@ export function encodeElements(values, elements, separator, version, context) {
24
26
  }
25
27
  }
26
28
  if (element.maxCount > 1) {
27
- textValues.push(values[elementIndex]?.map((value) => element.encode(value, context, version)).join(separator));
29
+ const elementValue = values[elementIndex];
30
+ textValues.push(Array.isArray(elementValue)
31
+ ? elementValue
32
+ .map((value) => element.encode(value, context, version))
33
+ .join(separator)
34
+ : undefined);
28
35
  }
29
36
  else {
30
37
  textValues.push(element.encode(values[elementIndex], context, version));
@@ -32,7 +39,12 @@ export function encodeElements(values, elements, separator, version, context) {
32
39
  }
33
40
  else {
34
41
  if (element.maxCount > 1) {
35
- textValues.push(values[element.name]?.map((value) => element.encode(value, context, version)).join(separator));
42
+ const elementValue = values[element.name];
43
+ textValues.push(Array.isArray(elementValue)
44
+ ? elementValue
45
+ .map((value) => element.encode(value, context, version))
46
+ .join(separator)
47
+ : undefined);
36
48
  }
37
49
  else {
38
50
  textValues.push(element.encode(values[element.name], context, version));
package/dist/format.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export function finTsEncode(value) {
2
- return value.replace(/([\?:\+'@])/g, '?$1');
2
+ return value.replace(/([?:+'@])/g, '?$1');
3
3
  }
4
4
  export function finTsDecode(value) {
5
- return value.replace(/\?([\?:\+'@])/g, '$1');
5
+ return value.replace(/\?([?:+'@])/g, '$1');
6
6
  }