@coderoftime/fints 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/CHANGELOG.md +519 -1
  2. package/README.md +138 -40
  3. package/dist/client.d.ts +49 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +242 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/core/account.d.ts +46 -7
  8. package/dist/core/account.d.ts.map +1 -1
  9. package/dist/core/account.js +143 -24
  10. package/dist/core/account.js.map +1 -1
  11. package/dist/core/amount.d.ts +15 -4
  12. package/dist/core/amount.d.ts.map +1 -1
  13. package/dist/core/amount.js +46 -9
  14. package/dist/core/amount.js.map +1 -1
  15. package/dist/core/balance.d.ts +4 -0
  16. package/dist/core/balance.d.ts.map +1 -1
  17. package/dist/core/balance.js +11 -5
  18. package/dist/core/balance.js.map +1 -1
  19. package/dist/core/bank-info.d.ts +21 -4
  20. package/dist/core/bank-info.d.ts.map +1 -1
  21. package/dist/core/bank-info.js +26 -5
  22. package/dist/core/bank-info.js.map +1 -1
  23. package/dist/core/client.d.ts +81 -19
  24. package/dist/core/client.d.ts.map +1 -1
  25. package/dist/core/config.d.ts +40 -20
  26. package/dist/core/config.d.ts.map +1 -1
  27. package/dist/core/config.js +85 -30
  28. package/dist/core/config.js.map +1 -1
  29. package/dist/core/errors.d.ts +100 -26
  30. package/dist/core/errors.d.ts.map +1 -1
  31. package/dist/core/errors.js +136 -53
  32. package/dist/core/errors.js.map +1 -1
  33. package/dist/core/feedback.d.ts +11 -1
  34. package/dist/core/feedback.d.ts.map +1 -1
  35. package/dist/core/feedback.js +14 -2
  36. package/dist/core/feedback.js.map +1 -1
  37. package/dist/core/transaction.d.ts +11 -1
  38. package/dist/core/transaction.d.ts.map +1 -1
  39. package/dist/core/transaction.js +21 -4
  40. package/dist/core/transaction.js.map +1 -1
  41. package/dist/core/transport.d.ts +48 -6
  42. package/dist/core/transport.d.ts.map +1 -1
  43. package/dist/core/transport.js +126 -29
  44. package/dist/core/transport.js.map +1 -1
  45. package/dist/formats/camt.d.ts +28 -5
  46. package/dist/formats/camt.d.ts.map +1 -1
  47. package/dist/formats/camt.js +132 -50
  48. package/dist/formats/camt.js.map +1 -1
  49. package/dist/formats/mt940.d.ts +29 -5
  50. package/dist/formats/mt940.d.ts.map +1 -1
  51. package/dist/formats/mt940.js +209 -113
  52. package/dist/formats/mt940.js.map +1 -1
  53. package/dist/formats/readers.d.ts +6 -2
  54. package/dist/formats/readers.d.ts.map +1 -1
  55. package/dist/formats/readers.js +28 -29
  56. package/dist/formats/readers.js.map +1 -1
  57. package/dist/formats/record-budget.d.ts +7 -0
  58. package/dist/formats/record-budget.d.ts.map +1 -0
  59. package/dist/formats/record-budget.js +17 -0
  60. package/dist/formats/record-budget.js.map +1 -0
  61. package/dist/formats/sepa-purpose.d.ts +9 -0
  62. package/dist/formats/sepa-purpose.d.ts.map +1 -1
  63. package/dist/formats/sepa-purpose.js +32 -2
  64. package/dist/formats/sepa-purpose.js.map +1 -1
  65. package/dist/index.d.ts +3 -3
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +2 -2
  68. package/dist/index.js.map +1 -1
  69. package/dist/session/app-approval.d.ts +11 -5
  70. package/dist/session/app-approval.d.ts.map +1 -1
  71. package/dist/session/app-approval.js +23 -12
  72. package/dist/session/app-approval.js.map +1 -1
  73. package/dist/session/dialog-runner.d.ts +11 -11
  74. package/dist/session/dialog-runner.d.ts.map +1 -1
  75. package/dist/session/dialog-runner.js +34 -19
  76. package/dist/session/dialog-runner.js.map +1 -1
  77. package/dist/session/login-guard.d.ts +54 -49
  78. package/dist/session/login-guard.d.ts.map +1 -1
  79. package/dist/session/login-guard.js +170 -83
  80. package/dist/session/login-guard.js.map +1 -1
  81. package/dist/session/sepa-accounts.d.ts +20 -14
  82. package/dist/session/sepa-accounts.d.ts.map +1 -1
  83. package/dist/session/sepa-accounts.js +62 -46
  84. package/dist/session/sepa-accounts.js.map +1 -1
  85. package/dist/session/session-setup.d.ts +41 -24
  86. package/dist/session/session-setup.d.ts.map +1 -1
  87. package/dist/session/session-setup.js +106 -63
  88. package/dist/session/session-setup.js.map +1 -1
  89. package/dist/session/session-state.d.ts +10 -6
  90. package/dist/session/session-state.d.ts.map +1 -1
  91. package/dist/session/session-state.js +72 -18
  92. package/dist/session/session-state.js.map +1 -1
  93. package/dist/session/signed-dialog.d.ts +83 -0
  94. package/dist/session/signed-dialog.d.ts.map +1 -0
  95. package/dist/session/signed-dialog.js +185 -0
  96. package/dist/session/signed-dialog.js.map +1 -0
  97. package/dist/session/tan-selection.d.ts +26 -18
  98. package/dist/session/tan-selection.d.ts.map +1 -1
  99. package/dist/session/tan-selection.js +44 -33
  100. package/dist/session/tan-selection.js.map +1 -1
  101. package/dist/session/user-prompts.d.ts +14 -5
  102. package/dist/session/user-prompts.d.ts.map +1 -1
  103. package/dist/session/user-prompts.js +53 -18
  104. package/dist/session/user-prompts.js.map +1 -1
  105. package/dist/tan/challenge.d.ts +47 -24
  106. package/dist/tan/challenge.d.ts.map +1 -1
  107. package/dist/tan/challenge.js +56 -51
  108. package/dist/tan/challenge.js.map +1 -1
  109. package/dist/tan/flicker.d.ts +11 -1
  110. package/dist/tan/flicker.d.ts.map +1 -1
  111. package/dist/tan/flicker.js +70 -24
  112. package/dist/tan/flicker.js.map +1 -1
  113. package/dist/tan/tan-image.d.ts +6 -2
  114. package/dist/tan/tan-image.d.ts.map +1 -1
  115. package/dist/tan/tan-image.js +14 -6
  116. package/dist/tan/tan-image.js.map +1 -1
  117. package/dist/tan/tan-models.d.ts +14 -2
  118. package/dist/tan/tan-models.d.ts.map +1 -1
  119. package/dist/tan/tan-models.js +24 -7
  120. package/dist/tan/tan-models.js.map +1 -1
  121. package/dist/util/arguments.d.ts +13 -0
  122. package/dist/util/arguments.d.ts.map +1 -0
  123. package/dist/util/arguments.js +40 -0
  124. package/dist/util/arguments.js.map +1 -0
  125. package/dist/util/async.d.ts +4 -3
  126. package/dist/util/async.d.ts.map +1 -1
  127. package/dist/util/async.js +6 -7
  128. package/dist/util/async.js.map +1 -1
  129. package/dist/util/bytes.d.ts +3 -4
  130. package/dist/util/bytes.d.ts.map +1 -1
  131. package/dist/util/bytes.js +13 -21
  132. package/dist/util/bytes.js.map +1 -1
  133. package/dist/util/call-context.d.ts.map +1 -1
  134. package/dist/util/call-context.js +3 -2
  135. package/dist/util/call-context.js.map +1 -1
  136. package/dist/util/dates.d.ts +6 -20
  137. package/dist/util/dates.d.ts.map +1 -1
  138. package/dist/util/dates.js +58 -28
  139. package/dist/util/dates.js.map +1 -1
  140. package/dist/util/errors.d.ts +13 -3
  141. package/dist/util/errors.d.ts.map +1 -1
  142. package/dist/util/errors.js +19 -6
  143. package/dist/util/errors.js.map +1 -1
  144. package/dist/util/immutable-map.d.ts +5 -2
  145. package/dist/util/immutable-map.d.ts.map +1 -1
  146. package/dist/util/immutable-map.js +15 -12
  147. package/dist/util/immutable-map.js.map +1 -1
  148. package/dist/util/inspect.d.ts +11 -0
  149. package/dist/util/inspect.d.ts.map +1 -0
  150. package/dist/util/inspect.js +14 -0
  151. package/dist/util/inspect.js.map +1 -0
  152. package/dist/util/json.d.ts +4 -0
  153. package/dist/util/json.d.ts.map +1 -1
  154. package/dist/util/json.js +18 -0
  155. package/dist/util/json.js.map +1 -1
  156. package/dist/util/text.d.ts +38 -5
  157. package/dist/util/text.d.ts.map +1 -1
  158. package/dist/util/text.js +90 -16
  159. package/dist/util/text.js.map +1 -1
  160. package/dist/util/xml.d.ts +9 -6
  161. package/dist/util/xml.d.ts.map +1 -1
  162. package/dist/util/xml.js +129 -56
  163. package/dist/util/xml.js.map +1 -1
  164. package/dist/v3/account-extension.d.ts.map +1 -1
  165. package/dist/v3/account-extension.js +7 -10
  166. package/dist/v3/account-extension.js.map +1 -1
  167. package/dist/v3/bank-connection.d.ts +54 -0
  168. package/dist/v3/bank-connection.d.ts.map +1 -0
  169. package/dist/v3/bank-connection.js +118 -0
  170. package/dist/v3/bank-connection.js.map +1 -0
  171. package/dist/v3/dialog.d.ts +84 -46
  172. package/dist/v3/dialog.d.ts.map +1 -1
  173. package/dist/v3/dialog.js +174 -60
  174. package/dist/v3/dialog.js.map +1 -1
  175. package/dist/v3/message.d.ts +32 -11
  176. package/dist/v3/message.d.ts.map +1 -1
  177. package/dist/v3/message.js +144 -83
  178. package/dist/v3/message.js.map +1 -1
  179. package/dist/v3/parameter-store.d.ts +111 -0
  180. package/dist/v3/parameter-store.d.ts.map +1 -0
  181. package/dist/v3/parameter-store.js +197 -0
  182. package/dist/v3/parameter-store.js.map +1 -0
  183. package/dist/v3/parameters.d.ts +44 -17
  184. package/dist/v3/parameters.d.ts.map +1 -1
  185. package/dist/v3/parameters.js +136 -60
  186. package/dist/v3/parameters.js.map +1 -1
  187. package/dist/v3/protocol.d.ts +50 -50
  188. package/dist/v3/protocol.d.ts.map +1 -1
  189. package/dist/v3/protocol.js +91 -210
  190. package/dist/v3/protocol.js.map +1 -1
  191. package/dist/v3/queries.d.ts +51 -0
  192. package/dist/v3/queries.d.ts.map +1 -0
  193. package/dist/v3/queries.js +128 -0
  194. package/dist/v3/queries.js.map +1 -0
  195. package/dist/v3/segments.d.ts +43 -19
  196. package/dist/v3/segments.d.ts.map +1 -1
  197. package/dist/v3/segments.js +84 -33
  198. package/dist/v3/segments.js.map +1 -1
  199. package/dist/v3/syntax.d.ts +68 -13
  200. package/dist/v3/syntax.d.ts.map +1 -1
  201. package/dist/v3/syntax.js +183 -102
  202. package/dist/v3/syntax.js.map +1 -1
  203. package/package.json +10 -6
  204. package/src/client.ts +293 -0
  205. package/src/core/account.ts +153 -24
  206. package/src/core/amount.ts +45 -10
  207. package/src/core/balance.ts +12 -5
  208. package/src/core/bank-info.ts +29 -5
  209. package/src/core/client.ts +83 -19
  210. package/src/core/config.ts +95 -35
  211. package/src/core/errors.ts +148 -54
  212. package/src/core/feedback.ts +16 -2
  213. package/src/core/transaction.ts +22 -4
  214. package/src/core/transport.ts +153 -32
  215. package/src/formats/camt.ts +153 -45
  216. package/src/formats/mt940.ts +244 -122
  217. package/src/formats/readers.ts +28 -31
  218. package/src/formats/record-budget.ts +18 -0
  219. package/src/formats/sepa-purpose.ts +29 -2
  220. package/src/index.ts +4 -2
  221. package/src/session/app-approval.ts +51 -38
  222. package/src/session/dialog-runner.ts +61 -31
  223. package/src/session/login-guard.ts +189 -87
  224. package/src/session/sepa-accounts.ts +63 -45
  225. package/src/session/session-setup.ts +105 -68
  226. package/src/session/session-state.ts +74 -23
  227. package/src/session/signed-dialog.ts +222 -0
  228. package/src/session/tan-selection.ts +50 -39
  229. package/src/session/user-prompts.ts +62 -18
  230. package/src/tan/challenge.ts +87 -64
  231. package/src/tan/flicker.ts +72 -23
  232. package/src/tan/tan-image.ts +15 -6
  233. package/src/tan/tan-models.ts +26 -7
  234. package/src/util/arguments.ts +40 -0
  235. package/src/util/async.ts +10 -9
  236. package/src/util/bytes.ts +14 -20
  237. package/src/util/call-context.ts +3 -2
  238. package/src/util/dates.ts +64 -33
  239. package/src/util/errors.ts +22 -6
  240. package/src/util/immutable-map.ts +15 -12
  241. package/src/util/inspect.ts +14 -0
  242. package/src/util/json.ts +16 -0
  243. package/src/util/text.ts +87 -15
  244. package/src/util/xml.ts +130 -52
  245. package/src/v3/account-extension.ts +7 -12
  246. package/src/v3/bank-connection.ts +126 -0
  247. package/src/v3/dialog.ts +186 -92
  248. package/src/v3/message.ts +140 -79
  249. package/src/v3/parameter-store.ts +226 -0
  250. package/src/v3/parameters.ts +166 -66
  251. package/src/v3/protocol.ts +103 -253
  252. package/src/v3/queries.ts +198 -0
  253. package/src/v3/segments.ts +86 -31
  254. package/src/v3/syntax.ts +172 -93
  255. package/dist/session/bank-connection.d.ts +0 -28
  256. package/dist/session/bank-connection.d.ts.map +0 -1
  257. package/dist/session/bank-connection.js +0 -48
  258. package/dist/session/bank-connection.js.map +0 -1
  259. package/dist/session/parameter-data.d.ts +0 -83
  260. package/dist/session/parameter-data.d.ts.map +0 -1
  261. package/dist/session/parameter-data.js +0 -68
  262. package/dist/session/parameter-data.js.map +0 -1
  263. package/dist/session/pin-tan-client.d.ts +0 -54
  264. package/dist/session/pin-tan-client.d.ts.map +0 -1
  265. package/dist/session/pin-tan-client.js +0 -153
  266. package/dist/session/pin-tan-client.js.map +0 -1
  267. package/dist/session/pin-tan-dialog.d.ts +0 -71
  268. package/dist/session/pin-tan-dialog.d.ts.map +0 -1
  269. package/dist/session/pin-tan-dialog.js +0 -124
  270. package/dist/session/pin-tan-dialog.js.map +0 -1
  271. package/dist/session/protocol.d.ts +0 -209
  272. package/dist/session/protocol.d.ts.map +0 -1
  273. package/dist/session/protocol.js +0 -75
  274. package/dist/session/protocol.js.map +0 -1
  275. package/dist/session/response-handler.d.ts +0 -48
  276. package/dist/session/response-handler.d.ts.map +0 -1
  277. package/dist/session/response-handler.js +0 -121
  278. package/dist/session/response-handler.js.map +0 -1
  279. package/dist/v3/client.d.ts +0 -24
  280. package/dist/v3/client.d.ts.map +0 -1
  281. package/dist/v3/client.js +0 -16
  282. package/dist/v3/client.js.map +0 -1
  283. package/src/session/bank-connection.ts +0 -51
  284. package/src/session/parameter-data.ts +0 -137
  285. package/src/session/pin-tan-client.ts +0 -186
  286. package/src/session/pin-tan-dialog.ts +0 -160
  287. package/src/session/protocol.ts +0 -311
  288. package/src/session/response-handler.ts +0 -130
  289. package/src/v3/client.ts +0 -29
@@ -1,32 +1,38 @@
1
- import type { Account } from '../core/account.js';
1
+ import { Account } from '../core/account.js';
2
+ import type { ParameterStore } from '../v3/parameter-store.js';
2
3
  import type { DialogRunner } from './dialog-runner.js';
3
- import type { LoginGuard } from './login-guard.js';
4
- import type { BankResponse, PinTanProtocol } from './protocol.js';
5
4
  import type { SessionState } from './session-state.js';
6
5
  /**
7
6
  * IBAN and BIC of the user's accounts, from the bank's SEPA account list where the user parameter data lack them
8
- * (Formals F.3.4).
7
+ * (Formals F.3.4), and the accounts the app passes completed from both.
9
8
  *
10
9
  * The list is read once per version of the user parameter data and kept in the saved state. Under version 0, which
11
- * holds for one dialog only (Formals E.2), without user parameter data, or where the bank rejects the list, it is kept
12
- * for this client only. Where the bank ends the dialog in answer to the list, the next call asks once more.
10
+ * holds for one dialog only (Formals E.2), without user parameter data, or where the bank rejects the list, also by
11
+ * ending the dialog, or names no account in it, it is kept for this client only: an empty list completes nothing, and
12
+ * saved it would outlast a fault of a single answer until the bank changes its user parameter data.
13
13
  */
14
- export declare class SepaAccounts<R extends BankResponse, O> {
15
- private readonly protocol;
14
+ export declare class SepaAccounts {
15
+ private readonly parameters;
16
16
  private readonly state;
17
17
  private readonly dialogs;
18
- private readonly guard;
19
18
  /**
20
19
  * The list this client keeps unsaved, with the version of the user parameter data it was read under; empty where the
21
- * bank rejected it.
20
+ * bank rejected it or named no account.
22
21
  */
23
22
  private unsaved;
24
- /** Whether a call already went on without the list because the bank ended the dialog in answer to it. */
25
- private abortSkipped;
26
- constructor(protocol: PinTanProtocol<R, O>, state: SessionState, dialogs: DialogRunner<R, O>, guard: LoginGuard);
23
+ constructor(parameters: ParameterStore, state: SessionState, dialogs: DialogRunner);
27
24
  /** The accounts of the user parameter data completed with IBAN and BIC, then the accounts only the list names. */
28
25
  completedAccounts(): Promise<Account[]>;
29
- /** `account` with IBAN and BIC filled in from the list. */
26
+ /**
27
+ * `account` as the bank knows it: the one of `completedAccounts` it matches, with what the bank states of it first,
28
+ * so that an account the app has built itself, such as from an IBAN alone, goes out with the account number, the
29
+ * sub-account and the BIC the bank's orders take, and the currency of its statements. Where the bank names none it
30
+ * matches, only what identifies `account`, and its currency: the rest, such as the transactions it permits, only the
31
+ * bank can state.
32
+ *
33
+ * Throws `FinTsUnsupportedError` for such an account where the user parameter data list all permitted transactions:
34
+ * they permit nothing for an account they leave out, and the client cannot tell it from a mistyped one.
35
+ */
30
36
  complete(account: Account): Promise<Account>;
31
37
  /** The list, read in the session's dialog, whose start delivers the user parameter data it is cached for. */
32
38
  private list;
@@ -1 +1 @@
1
- {"version":3,"file":"sepa-accounts.d.ts","sourceRoot":"","sources":["../../src/session/sepa-accounts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;GAOG;AACH,qBAAa,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC;IAW/C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAbxB;;;OAGG;IACH,OAAO,CAAC,OAAO,CAA+E;IAE9F,yGAAyG;IACzG,OAAO,CAAC,YAAY,CAAS;gBAGV,QAAQ,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAC9B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,KAAK,EAAE,UAAU;IAGpC,kHAAkH;IAC5G,iBAAiB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAS7C,2DAA2D;IACrD,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlD,6GAA6G;YAC/F,IAAI;CAwCnB"}
1
+ {"version":3,"file":"sepa-accounts.d.ts","sourceRoot":"","sources":["../../src/session/sepa-accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgB,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IAQrB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAT1B;;;OAGG;IACH,OAAO,CAAC,OAAO,CAA+E;gBAG3E,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,YAAY;IAGxC,kHAAkH;IAC5G,iBAAiB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAW7C;;;;;;;;;OASG;IACG,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BlD,6GAA6G;YAC/F,IAAI;CA0BnB"}
@@ -1,49 +1,80 @@
1
- import { FinTsDialogAbortedError } from '../core/errors.js';
1
+ import { Account, AccountIndex } from '../core/account.js';
2
+ import { FinTsUnsupportedError, tryLookUp } from '../core/errors.js';
3
+ import { sepaAccountsQuery } from '../v3/queries.js';
2
4
  /**
3
5
  * IBAN and BIC of the user's accounts, from the bank's SEPA account list where the user parameter data lack them
4
- * (Formals F.3.4).
6
+ * (Formals F.3.4), and the accounts the app passes completed from both.
5
7
  *
6
8
  * The list is read once per version of the user parameter data and kept in the saved state. Under version 0, which
7
- * holds for one dialog only (Formals E.2), without user parameter data, or where the bank rejects the list, it is kept
8
- * for this client only. Where the bank ends the dialog in answer to the list, the next call asks once more.
9
+ * holds for one dialog only (Formals E.2), without user parameter data, or where the bank rejects the list, also by
10
+ * ending the dialog, or names no account in it, it is kept for this client only: an empty list completes nothing, and
11
+ * saved it would outlast a fault of a single answer until the bank changes its user parameter data.
9
12
  */
10
13
  export class SepaAccounts {
11
- protocol;
14
+ parameters;
12
15
  state;
13
16
  dialogs;
14
- guard;
15
17
  /**
16
18
  * The list this client keeps unsaved, with the version of the user parameter data it was read under; empty where the
17
- * bank rejected it.
19
+ * bank rejected it or named no account.
18
20
  */
19
21
  unsaved;
20
- /** Whether a call already went on without the list because the bank ended the dialog in answer to it. */
21
- abortSkipped = false;
22
- constructor(protocol, state, dialogs, guard) {
23
- this.protocol = protocol;
22
+ constructor(parameters, state, dialogs) {
23
+ this.parameters = parameters;
24
24
  this.state = state;
25
25
  this.dialogs = dialogs;
26
- this.guard = guard;
27
26
  }
28
27
  /** The accounts of the user parameter data completed with IBAN and BIC, then the accounts only the list names. */
29
28
  async completedAccounts() {
30
29
  const sepa = await this.list();
31
- const accounts = this.protocol.userParameters?.accounts ?? [];
30
+ const accounts = this.parameters.userParameters?.accounts ?? [];
31
+ const listed = new AccountIndex(sepa);
32
+ const known = new AccountIndex(accounts);
32
33
  return [
33
- ...accounts.map((account) => withSepaDetails(account, sepa)),
34
- ...sepa.filter((s) => !accounts.some((a) => s.matches(a))),
34
+ ...accounts.map((account) => withSepaDetails(account, listed.find(account))),
35
+ ...sepa.filter((s) => known.find(s) === undefined),
35
36
  ];
36
37
  }
37
- /** `account` with IBAN and BIC filled in from the list. */
38
+ /**
39
+ * `account` as the bank knows it: the one of `completedAccounts` it matches, with what the bank states of it first,
40
+ * so that an account the app has built itself, such as from an IBAN alone, goes out with the account number, the
41
+ * sub-account and the BIC the bank's orders take, and the currency of its statements. Where the bank names none it
42
+ * matches, only what identifies `account`, and its currency: the rest, such as the transactions it permits, only the
43
+ * bank can state.
44
+ *
45
+ * Throws `FinTsUnsupportedError` for such an account where the user parameter data list all permitted transactions:
46
+ * they permit nothing for an account they leave out, and the client cannot tell it from a mistyped one.
47
+ */
38
48
  async complete(account) {
39
- if (account.iban !== undefined && account.bic !== undefined)
40
- return account;
41
- return withSepaDetails(account, await this.list());
49
+ const known = (await this.completedAccounts()).find((a) => account.matches(a));
50
+ if (known !== undefined) {
51
+ // A sub-account belongs to the account number it comes with.
52
+ const national = known.accountNumber === undefined ? account : known;
53
+ return known.copyWith({
54
+ accountNumber: national.accountNumber,
55
+ subAccount: national.subAccount,
56
+ iban: known.iban ?? account.iban,
57
+ bic: known.bic ?? account.bic,
58
+ currency: known.currency ?? account.currency,
59
+ });
60
+ }
61
+ if (this.parameters.userParameters?.listsAllTransactions === true) {
62
+ throw new FinTsUnsupportedError("The bank does not name this account among the user's, and so permits nothing");
63
+ }
64
+ return new Account({
65
+ accountNumber: account.accountNumber,
66
+ subAccount: account.subAccount,
67
+ bankCode: account.bankCode,
68
+ countryCode: account.countryCode,
69
+ iban: account.iban,
70
+ bic: account.bic,
71
+ currency: account.currency,
72
+ });
42
73
  }
43
74
  /** The list, read in the session's dialog, whose start delivers the user parameter data it is cached for. */
44
75
  async list() {
45
76
  await this.dialogs.open();
46
- const upd = this.protocol.userParameters;
77
+ const upd = this.parameters.userParameters;
47
78
  if (upd !== undefined &&
48
79
  upd.accounts.length > 0 &&
49
80
  upd.accounts.every((a) => a.iban !== undefined && a.bic !== undefined)) {
@@ -55,29 +86,13 @@ export class SepaAccounts {
55
86
  return saved;
56
87
  if (this.unsaved !== undefined && this.unsaved.updVersion === updVersion)
57
88
  return this.unsaved.accounts;
58
- const query = this.protocol.sepaAccounts();
89
+ const query = sepaAccountsQuery(this.parameters);
59
90
  if (query === undefined)
60
91
  return [];
61
- // Where the bank rejects the list, the accounts stay as the user parameter data state them.
62
- const outcome = { aborted: false };
63
- const accounts = await this.guard.tryLookUp(async () => {
64
- try {
65
- return await this.dialogs.query(() => query);
66
- }
67
- catch (error) {
68
- if (error instanceof FinTsDialogAbortedError)
69
- outcome.aborted = true;
70
- throw error;
71
- }
72
- });
73
- if (outcome.aborted && !this.abortSkipped) {
74
- // The bank may have ended the dialog for a reason of its own, such as a timeout, so this call goes on without the
75
- // list and the next one asks again in its new dialog. Only once: banks also end the dialog when they reject the
76
- // list, and each time costs the next call a login.
77
- this.abortSkipped = true;
78
- return [];
79
- }
80
- if (accounts !== undefined && updVersion !== undefined && updVersion > 0) {
92
+ // Where the bank rejects the list, also by ending the dialog, the accounts stay as the user parameter data state
93
+ // them: asked again, a bank that ends the dialog in answer would cost each call a login.
94
+ const accounts = await tryLookUp(() => this.dialogs.query(() => query));
95
+ if (accounts !== undefined && accounts.length > 0 && updVersion !== undefined && updVersion > 0) {
81
96
  this.state.cacheSepaAccounts(accounts, updVersion);
82
97
  }
83
98
  else {
@@ -86,11 +101,12 @@ export class SepaAccounts {
86
101
  return accounts ?? [];
87
102
  }
88
103
  }
89
- function withSepaDetails(account, sepa) {
90
- const match = sepa.find((s) => account.matches(s));
91
- if (match === undefined)
92
- return account;
104
+ /**
105
+ * A copy of `account`, which shares no date with the user parameter data, with the IBAN and BIC of `match`, its entry
106
+ * in the SEPA account list, if any.
107
+ */
108
+ function withSepaDetails(account, match) {
93
109
  // A BIC of the list takes precedence over the one of the user parameter data (Formals E.3.1.1, "BIC").
94
- return account.copyWith({ iban: account.iban ?? match.iban, bic: match.bic ?? account.bic });
110
+ return account.copyWith({ iban: account.iban ?? match?.iban, bic: match?.bic ?? account.bic });
95
111
  }
96
112
  //# sourceMappingURL=sepa-accounts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sepa-accounts.js","sourceRoot":"","sources":["../../src/session/sepa-accounts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sepa-accounts.js","sourceRoot":"","sources":["../../src/session/sepa-accounts.ts"],"names":[],"mappings":"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"}
@@ -1,23 +1,20 @@
1
1
  import type { BankInfo } from '../core/bank-info.js';
2
- import type { TanMethod } from '../tan/tan-models.js';
3
- import type { LoginGuard } from './login-guard.js';
4
- import type { BankResponse, PinTanProtocol, ProtocolDialog } from './protocol.js';
5
- import type { ResponseHandler } from './response-handler.js';
2
+ import type { TanMedium, TanMethod } from '../tan/tan-models.js';
3
+ import type { FinTs3Protocol } from '../v3/protocol.js';
4
+ import { SignedDialog, type SessionParts } from './signed-dialog.js';
6
5
  import type { TanSelection } from './tan-selection.js';
7
6
  /**
8
7
  * What has to be settled before a login: the bank parameter data, the synchronization, and through `TanSelection` the
9
8
  * TAN method and medium. Each of the dialogs this takes serves one purpose only.
10
9
  *
11
- * Where the bank refuses a login for a reason the session can take care of, `remedied` does so and logs in again.
10
+ * Where the bank refuses a login for a reason the session can take care of, `remedied` does so and logs in again; so it
11
+ * does where the limits of bank parameter data that may be outdated keep a login from going out.
12
12
  */
13
- export declare class SessionSetup<R extends BankResponse, O> {
13
+ export declare class SessionSetup {
14
+ private readonly session;
14
15
  private readonly protocol;
15
- private readonly responses;
16
16
  private readonly tans;
17
- private readonly guard;
18
- /** Whether a synchronization dialog ran, so that a helpful one runs once only. */
19
- private synchronizationTried;
20
- constructor(protocol: PinTanProtocol<R, O>, responses: ResponseHandler<R>, tans: TanSelection<R, O>, guard: LoginGuard);
17
+ constructor(session: SessionParts, protocol: FinTs3Protocol, tans: TanSelection);
21
18
  /**
22
19
  * The bank's general information: from an anonymous dialog where the bank answers one, else from the synchronization.
23
20
  * No TAN method or medium is chosen for it.
@@ -25,21 +22,26 @@ export declare class SessionSetup<R extends BankResponse, O> {
25
22
  bankInfo(): Promise<BankInfo>;
26
23
  /** The TAN methods the bank allows for this user, which the synchronization reports. */
27
24
  methods(): Promise<TanMethod[]>;
28
- /** Settles what is still open: the bank parameter data, the synchronization, the TAN method and medium. */
29
- prepare(): Promise<void>;
25
+ /**
26
+ * Settles what is still open: the bank parameter data, the synchronization, the TAN method and medium. Returns the TAN
27
+ * media it looked up to choose the medium; `undefined` where it looked up none, or the bank listed none.
28
+ */
29
+ prepare(): Promise<TanMedium[] | undefined>;
30
30
  /** A new dialog signed with the TAN method and medium in use, once `prepare` has settled them. */
31
- newDialog(): Promise<ProtocolDialog<R, O>>;
31
+ newDialog(): Promise<SignedDialog>;
32
32
  /**
33
- * Runs `attempt`, which may log in, and runs it once more for each reason of a refused login the session can take
34
- * care of, so that a bank that keeps refusing fails with its own error:
33
+ * Runs `attempt`, which may log in, once more after each refused login `remedy` takes care of.
35
34
  *
36
- * | Refusal (`LoginGuard.remediableReasons`) | Remedy |
37
- * | --- | --- |
38
- * | 3920 without the method, or 9075 after the one-step method | another allowed method (`TanSelection.replace`) |
39
- * | 9391 | a new synchronization, which issues a customer system ID |
35
+ * Where the limits of the bank parameter data kept a login from going out (`FinTs3Protocol.stoppedLogin`), it fetches
36
+ * them anew in an anonymous dialog, once, and runs `attempt` once more: they may be outdated, as saved ones are, and
37
+ * new ones would come only in answer to the login they rule out. The new limits judge the login built anew, not the
38
+ * one stopped: it reports version 0 for the parameter data they stand in for, so it may be shorter.
40
39
  */
41
40
  remedied<T>(attempt: () => Promise<T>): Promise<T>;
42
- /** Takes care of `reason`, given for refusing a login signed with `rejected`; returns whether it could. */
41
+ /**
42
+ * Takes care of `reason`, given for refusing a login signed with `rejected`, with another TAN method or a new
43
+ * synchronization; returns whether it could.
44
+ */
43
45
  private remedy;
44
46
  /**
45
47
  * Loads the bank parameter data if they are missing, then synchronizes if that is due.
@@ -52,11 +54,26 @@ export declare class SessionSetup<R extends BankResponse, O> {
52
54
  */
53
55
  private loadParameters;
54
56
  /**
55
- * Asks for the bank parameter data without logging in. A bank that does not answer anonymously is no error, but a
56
- * failed connection is: the synchronization would only wait for the same server again.
57
+ * Asks for the bank parameter data without logging in, keeps them where there are none from a dialog signed with the
58
+ * PIN (`ParameterStore.keepAnonymous`), or with `refresh` their limits only (`ParameterStore.keepRefreshedLimits`),
59
+ * and passes the bank's messages on: all an anonymous dialog tells, since the TAN methods it lists are not those of a
60
+ * user. A bank that does not answer anonymously is no error, but a failed connection is: the synchronization would
61
+ * only wait for the same server again.
57
62
  */
58
63
  private fetchBankParametersAnonymously;
59
- /** Runs the synchronization dialog where it is due (`TanSelection.synchronizationDialog`). */
64
+ /**
65
+ * Asks for the bank parameter data in an anonymous dialog that announces strong customer authentication; a bank that
66
+ * rejects the announcement, with a return code or by failing on it, is asked again without it.
67
+ *
68
+ * A timeout or a broken connection is not a reason to ask again: it would only double the wait.
69
+ */
70
+ private requestBankParametersAnonymously;
71
+ private anonymousDialog;
72
+ /**
73
+ * Runs the synchronization, a login in a dialog of its own, while there is no customer system ID, without which no
74
+ * regular dialog starts. It runs before the TAN method and medium are settled (`TanSelection.synchronizationDialog`
75
+ * tells which method signs it).
76
+ */
60
77
  private synchronizeIfDue;
61
78
  /**
62
79
  * The TAN media of the method in use; `undefined` if the bank does not list them or rejects the list, after which the
@@ -1 +1 @@
1
- {"version":3,"file":"session-setup.d.ts","sourceRoot":"","sources":["../../src/session/session-setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAa,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,qBAAa,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC;IAK/C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPxB,kFAAkF;IAClF,OAAO,CAAC,oBAAoB,CAAS;gBAGlB,QAAQ,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAC9B,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,EAC7B,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EACxB,KAAK,EAAE,UAAU;IAGpC;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IAMnC,wFAAwF;IAClF,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAKrC,2GAA2G;IACrG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B,kGAAkG;IAC5F,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAKhD;;;;;;;;OAQG;IACG,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBxD,2GAA2G;YAC7F,MAAM;IAYpB;;;;;;;;OAQG;YACW,cAAc;IAM5B;;;OAGG;YACW,8BAA8B;IAS5C,8FAA8F;YAChF,gBAAgB;IAc9B;;;;;;OAMG;YACW,cAAc;IAW5B,+FAA+F;YACjF,IAAI;CAOnB"}
1
+ {"version":3,"file":"session-setup.d.ts","sourceRoot":"","sources":["../../src/session/session-setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;GAMG;AACH,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,YAAY;IAGrC;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IAMnC,wFAAwF;IAClF,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAKrC;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,GAAG,SAAS,CAAC;IASjD,kGAAkG;IAC5F,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAKxC;;;;;;;OAOG;IACG,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYxD;;;OAGG;YACW,MAAM;IAYpB;;;;;;;;OAQG;YACW,cAAc;IAM5B;;;;;;OAMG;YACW,8BAA8B;IAY5C;;;;;OAKG;YACW,gCAAgC;YAahC,eAAe;IAS7B;;;;OAIG;YACW,gBAAgB;IAS9B;;;;;;OAMG;YACW,cAAc;IAW5B,+FAA+F;YACjF,IAAI;CAQnB"}
@@ -1,93 +1,93 @@
1
- import { FinTsBankError, FinTsError, FinTsProtocolError, FinTsTransportError, parseBankData } from '../core/errors.js';
2
- import { requireBankParameters } from './parameter-data.js';
1
+ import { FinTsError, FinTsProtocolError, FinTsTransportError, parseBankData, tryLookUp } from '../core/errors.js';
2
+ import { hasErrors } from '../core/feedback.js';
3
+ import { FinTs3Dialog } from '../v3/dialog.js';
4
+ import { requireBankParameters } from '../v3/parameters.js';
5
+ import { tanMediaQuery } from '../v3/queries.js';
6
+ import { SignedDialog } from './signed-dialog.js';
3
7
  /**
4
8
  * What has to be settled before a login: the bank parameter data, the synchronization, and through `TanSelection` the
5
9
  * TAN method and medium. Each of the dialogs this takes serves one purpose only.
6
10
  *
7
- * Where the bank refuses a login for a reason the session can take care of, `remedied` does so and logs in again.
11
+ * Where the bank refuses a login for a reason the session can take care of, `remedied` does so and logs in again; so it
12
+ * does where the limits of bank parameter data that may be outdated keep a login from going out.
8
13
  */
9
14
  export class SessionSetup {
15
+ session;
10
16
  protocol;
11
- responses;
12
17
  tans;
13
- guard;
14
- /** Whether a synchronization dialog ran, so that a helpful one runs once only. */
15
- synchronizationTried = false;
16
- constructor(protocol, responses, tans, guard) {
18
+ constructor(session, protocol, tans) {
19
+ this.session = session;
17
20
  this.protocol = protocol;
18
- this.responses = responses;
19
21
  this.tans = tans;
20
- this.guard = guard;
21
22
  }
22
23
  /**
23
24
  * The bank's general information: from an anonymous dialog where the bank answers one, else from the synchronization.
24
25
  * No TAN method or medium is chosen for it.
25
26
  */
26
27
  async bankInfo() {
27
- if (this.protocol.bankParameters === undefined)
28
+ if (this.session.parameters.bankParameters === undefined)
28
29
  await this.fetchBankParametersAnonymously();
29
- if (this.protocol.bankParameters === undefined)
30
+ if (this.session.parameters.bankParameters === undefined)
30
31
  await this.synchronizeIfDue();
31
- return requireBankParameters(this.protocol.bankParameters).bankInfo;
32
+ return requireBankParameters(this.session.parameters.bankParameters).bankInfo;
32
33
  }
33
34
  /** The TAN methods the bank allows for this user, which the synchronization reports. */
34
35
  async methods() {
35
36
  await this.loadParameters();
36
37
  return this.tans.available();
37
38
  }
38
- /** Settles what is still open: the bank parameter data, the synchronization, the TAN method and medium. */
39
+ /**
40
+ * Settles what is still open: the bank parameter data, the synchronization, the TAN method and medium. Returns the TAN
41
+ * media it looked up to choose the medium; `undefined` where it looked up none, or the bank listed none.
42
+ */
39
43
  async prepare() {
40
44
  await this.loadParameters();
41
45
  await this.tans.ensureMethodChosen();
42
- if (this.tans.mediumToLookUp)
43
- await this.tans.chooseMedium(await this.lookUpTanMedia());
46
+ if (!this.tans.mediumToLookUp)
47
+ return undefined;
48
+ const media = await this.lookUpTanMedia();
49
+ await this.tans.chooseMedium(media);
50
+ return media;
44
51
  }
45
52
  /** A new dialog signed with the TAN method and medium in use, once `prepare` has settled them. */
46
53
  async newDialog() {
47
54
  await this.prepare();
48
- return this.tans.newDialog();
55
+ return new SignedDialog(this.tans.newDialog(), this.session);
49
56
  }
50
57
  /**
51
- * Runs `attempt`, which may log in, and runs it once more for each reason of a refused login the session can take
52
- * care of, so that a bank that keeps refusing fails with its own error:
58
+ * Runs `attempt`, which may log in, once more after each refused login `remedy` takes care of.
53
59
  *
54
- * | Refusal (`LoginGuard.remediableReasons`) | Remedy |
55
- * | --- | --- |
56
- * | 3920 without the method, or 9075 after the one-step method | another allowed method (`TanSelection.replace`) |
57
- * | 9391 | a new synchronization, which issues a customer system ID |
60
+ * Where the limits of the bank parameter data kept a login from going out (`FinTs3Protocol.stoppedLogin`), it fetches
61
+ * them anew in an anonymous dialog, once, and runs `attempt` once more: they may be outdated, as saved ones are, and
62
+ * new ones would come only in answer to the login they rule out. The new limits judge the login built anew, not the
63
+ * one stopped: it reports version 0 for the parameter data they stand in for, so it may be shorter.
58
64
  */
59
65
  async remedied(attempt) {
60
- // A refusal of an earlier call stops the attempt before it sends the PIN; there is nothing to remedy.
61
- if (this.guard.hasRefusal)
62
- return attempt();
63
- const remedied = new Set();
64
- for (;;) {
65
- try {
66
- return await attempt();
67
- }
68
- catch (error) {
69
- if (!(error instanceof FinTsBankError))
70
- throw error;
71
- const reason = this.guard.remediableReasons(error).find((r) => !remedied.has(r));
72
- const rejected = this.guard.refusedMethod;
73
- if (reason === undefined || rejected === undefined || !(await this.remedy(reason, rejected)))
74
- throw error;
75
- remedied.add(reason);
76
- this.guard.pardon(error);
77
- }
66
+ const run = () => this.session.guard.remedied(attempt, (reason, rejected) => this.remedy(reason, rejected));
67
+ try {
68
+ return await run();
69
+ }
70
+ catch (error) {
71
+ if (!this.protocol.stoppedLogin(error))
72
+ throw error;
73
+ await this.fetchBankParametersAnonymously(true);
74
+ return run();
78
75
  }
79
76
  }
80
- /** Takes care of `reason`, given for refusing a login signed with `rejected`; returns whether it could. */
77
+ /**
78
+ * Takes care of `reason`, given for refusing a login signed with `rejected`, with another TAN method or a new
79
+ * synchronization; returns whether it could.
80
+ */
81
81
  async remedy(reason, rejected) {
82
82
  switch (reason) {
83
83
  case 'tanMethodNotAllowed':
84
84
  // The parameter data name the methods to choose from; the refusal may be the first to deliver them.
85
- if (this.protocol.bankParameters === undefined)
85
+ if (this.session.parameters.bankParameters === undefined)
86
86
  await this.fetchBankParametersAnonymously();
87
87
  return this.tans.replace(rejected);
88
88
  case 'systemIdRejected':
89
89
  // Without a customer system ID there is none to lose, and logging in once more would only send the PIN again.
90
- return this.protocol.forgetSystemId();
90
+ return this.session.parameters.forgetSystemId();
91
91
  }
92
92
  }
93
93
  /**
@@ -100,18 +100,27 @@ export class SessionSetup {
100
100
  * After a refused login it throws the refusal right away, before the user is asked for a TAN method or medium.
101
101
  */
102
102
  async loadParameters() {
103
- this.guard.check();
104
- if (this.protocol.bankParameters === undefined)
103
+ this.session.guard.check();
104
+ if (this.session.parameters.bankParameters === undefined)
105
105
  await this.fetchBankParametersAnonymously();
106
106
  await this.synchronizeIfDue();
107
107
  }
108
108
  /**
109
- * Asks for the bank parameter data without logging in. A bank that does not answer anonymously is no error, but a
110
- * failed connection is: the synchronization would only wait for the same server again.
109
+ * Asks for the bank parameter data without logging in, keeps them where there are none from a dialog signed with the
110
+ * PIN (`ParameterStore.keepAnonymous`), or with `refresh` their limits only (`ParameterStore.keepRefreshedLimits`),
111
+ * and passes the bank's messages on: all an anonymous dialog tells, since the TAN methods it lists are not those of a
112
+ * user. A bank that does not answer anonymously is no error, but a failed connection is: the synchronization would
113
+ * only wait for the same server again.
111
114
  */
112
- async fetchBankParametersAnonymously() {
115
+ async fetchBankParametersAnonymously(refresh = false) {
113
116
  try {
114
- this.responses.showBankMessages(await this.protocol.fetchBankParametersAnonymously());
117
+ const response = await this.requestBankParametersAnonymously();
118
+ if (refresh)
119
+ this.session.parameters.keepRefreshedLimits(response);
120
+ else
121
+ this.session.parameters.keepAnonymous(response);
122
+ for (const message of response.bankMessages)
123
+ this.session.prompts.showBankMessage(message);
115
124
  }
116
125
  catch (error) {
117
126
  // Optional: the login delivers the parameters as well.
@@ -119,15 +128,48 @@ export class SessionSetup {
119
128
  throw error;
120
129
  }
121
130
  }
122
- /** Runs the synchronization dialog where it is due (`TanSelection.synchronizationDialog`). */
131
+ /**
132
+ * Asks for the bank parameter data in an anonymous dialog that announces strong customer authentication; a bank that
133
+ * rejects the announcement, with a return code or by failing on it, is asked again without it.
134
+ *
135
+ * A timeout or a broken connection is not a reason to ask again: it would only double the wait.
136
+ */
137
+ async requestBankParametersAnonymously() {
138
+ let announced;
139
+ try {
140
+ announced = await this.anonymousDialog(true);
141
+ }
142
+ catch (error) {
143
+ if (error instanceof FinTsTransportError && error.statusCode === undefined)
144
+ throw error;
145
+ if (!(error instanceof FinTsError))
146
+ throw error;
147
+ return this.anonymousDialog(false);
148
+ }
149
+ if (!hasErrors(announced.feedback) || announced.find('HIBPA') !== undefined)
150
+ return announced;
151
+ return this.anonymousDialog(false);
152
+ }
153
+ async anonymousDialog(announceSca) {
154
+ const dialog = FinTs3Dialog.anonymous(this.protocol);
155
+ try {
156
+ return await dialog.requestBankParameters(announceSca);
157
+ }
158
+ finally {
159
+ await dialog.end();
160
+ }
161
+ }
162
+ /**
163
+ * Runs the synchronization, a login in a dialog of its own, while there is no customer system ID, without which no
164
+ * regular dialog starts. It runs before the TAN method and medium are settled (`TanSelection.synchronizationDialog`
165
+ * tells which method signs it).
166
+ */
123
167
  async synchronizeIfDue() {
124
- const due = this.protocol.synchronization === 'required' ||
125
- (this.protocol.synchronization === 'helpful' && !this.synchronizationTried);
126
- if (!due)
168
+ if (this.session.parameters.systemId !== undefined)
127
169
  return;
128
- this.synchronizationTried = true;
129
- await this.once(this.tans.synchronizationDialog(), (dialog) => this.responses.startDialog(dialog, () => dialog.start(true)));
130
- if (this.protocol.synchronization === 'required') {
170
+ await this.once(this.tans.synchronizationDialog(), (dialog) => dialog.login(true));
171
+ // Set by the synchronization, which the compiler cannot see.
172
+ if (this.session.parameters.systemId === undefined) {
131
173
  throw new FinTsProtocolError('The bank did not complete the synchronization');
132
174
  }
133
175
  }
@@ -139,21 +181,22 @@ export class SessionSetup {
139
181
  * medium the list tells (PIN/TAN B.4.3.1.3).
140
182
  */
141
183
  async lookUpTanMedia() {
142
- const query = this.protocol.tanMedia();
184
+ const query = tanMediaQuery(this.session.parameters);
143
185
  if (query === undefined)
144
186
  return undefined;
145
- return this.guard.tryLookUp(() => this.once(this.tans.lookupDialog(), async (dialog) => {
146
- const pages = await this.responses.startDialogWith(dialog, dialog.startWith(query.order(undefined)));
147
- return parseBankData(() => query.read(pages));
187
+ return tryLookUp(() => this.once(this.tans.lookupDialog(), async (dialog) => {
188
+ const answers = await dialog.loginWith(query.order(undefined));
189
+ return parseBankData(() => query.read(answers));
148
190
  }));
149
191
  }
150
192
  /** Runs `use` in `dialog`, a dialog of its own, and ends it afterwards, however `use` ends. */
151
193
  async once(dialog, use) {
194
+ const signed = new SignedDialog(dialog, this.session);
152
195
  try {
153
- return await use(dialog);
196
+ return await use(signed);
154
197
  }
155
198
  finally {
156
- await dialog.end();
199
+ await signed.end();
157
200
  }
158
201
  }
159
202
  }