@coderoftime/fints 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +28 -0
  3. package/README.md +156 -2
  4. package/dist/core/account.d.ts +140 -0
  5. package/dist/core/account.d.ts.map +1 -0
  6. package/dist/core/account.js +174 -0
  7. package/dist/core/account.js.map +1 -0
  8. package/dist/core/amount.d.ts +62 -0
  9. package/dist/core/amount.d.ts.map +1 -0
  10. package/dist/core/amount.js +189 -0
  11. package/dist/core/amount.js.map +1 -0
  12. package/dist/core/balance.d.ts +54 -0
  13. package/dist/core/balance.d.ts.map +1 -0
  14. package/dist/core/balance.js +53 -0
  15. package/dist/core/balance.js.map +1 -0
  16. package/dist/core/bank-info.d.ts +49 -0
  17. package/dist/core/bank-info.d.ts.map +1 -0
  18. package/dist/core/bank-info.js +52 -0
  19. package/dist/core/bank-info.js.map +1 -0
  20. package/dist/core/client.d.ts +126 -0
  21. package/dist/core/client.d.ts.map +1 -0
  22. package/dist/core/client.js +2 -0
  23. package/dist/core/client.js.map +1 -0
  24. package/dist/core/config.d.ts +68 -0
  25. package/dist/core/config.d.ts.map +1 -0
  26. package/dist/core/config.js +113 -0
  27. package/dist/core/config.js.map +1 -0
  28. package/dist/core/errors.d.ts +91 -0
  29. package/dist/core/errors.d.ts.map +1 -0
  30. package/dist/core/errors.js +182 -0
  31. package/dist/core/errors.js.map +1 -0
  32. package/dist/core/feedback.d.ts +69 -0
  33. package/dist/core/feedback.d.ts.map +1 -0
  34. package/dist/core/feedback.js +124 -0
  35. package/dist/core/feedback.js.map +1 -0
  36. package/dist/core/transaction.d.ts +98 -0
  37. package/dist/core/transaction.d.ts.map +1 -0
  38. package/dist/core/transaction.js +91 -0
  39. package/dist/core/transaction.js.map +1 -0
  40. package/dist/core/transport.d.ts +37 -0
  41. package/dist/core/transport.d.ts.map +1 -0
  42. package/dist/core/transport.js +92 -0
  43. package/dist/core/transport.js.map +1 -0
  44. package/dist/formats/camt.d.ts +12 -0
  45. package/dist/formats/camt.d.ts.map +1 -0
  46. package/dist/formats/camt.js +159 -0
  47. package/dist/formats/camt.js.map +1 -0
  48. package/dist/formats/mt940.d.ts +42 -0
  49. package/dist/formats/mt940.d.ts.map +1 -0
  50. package/dist/formats/mt940.js +297 -0
  51. package/dist/formats/mt940.js.map +1 -0
  52. package/dist/formats/readers.d.ts +11 -0
  53. package/dist/formats/readers.d.ts.map +1 -0
  54. package/dist/formats/readers.js +47 -0
  55. package/dist/formats/readers.js.map +1 -0
  56. package/dist/formats/sepa-purpose.d.ts +22 -0
  57. package/dist/formats/sepa-purpose.d.ts.map +1 -0
  58. package/dist/formats/sepa-purpose.js +68 -0
  59. package/dist/formats/sepa-purpose.js.map +1 -0
  60. package/dist/index.d.ts +28 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +27 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/session/app-approval.d.ts +60 -0
  65. package/dist/session/app-approval.d.ts.map +1 -0
  66. package/dist/session/app-approval.js +215 -0
  67. package/dist/session/app-approval.js.map +1 -0
  68. package/dist/session/bank-connection.d.ts +28 -0
  69. package/dist/session/bank-connection.d.ts.map +1 -0
  70. package/dist/session/bank-connection.js +48 -0
  71. package/dist/session/bank-connection.js.map +1 -0
  72. package/dist/session/dialog-runner.d.ts +34 -0
  73. package/dist/session/dialog-runner.d.ts.map +1 -0
  74. package/dist/session/dialog-runner.js +112 -0
  75. package/dist/session/dialog-runner.js.map +1 -0
  76. package/dist/session/login-guard.d.ts +73 -0
  77. package/dist/session/login-guard.d.ts.map +1 -0
  78. package/dist/session/login-guard.js +109 -0
  79. package/dist/session/login-guard.js.map +1 -0
  80. package/dist/session/parameter-data.d.ts +83 -0
  81. package/dist/session/parameter-data.d.ts.map +1 -0
  82. package/dist/session/parameter-data.js +68 -0
  83. package/dist/session/parameter-data.js.map +1 -0
  84. package/dist/session/pin-tan-client.d.ts +54 -0
  85. package/dist/session/pin-tan-client.d.ts.map +1 -0
  86. package/dist/session/pin-tan-client.js +153 -0
  87. package/dist/session/pin-tan-client.js.map +1 -0
  88. package/dist/session/pin-tan-dialog.d.ts +71 -0
  89. package/dist/session/pin-tan-dialog.d.ts.map +1 -0
  90. package/dist/session/pin-tan-dialog.js +124 -0
  91. package/dist/session/pin-tan-dialog.js.map +1 -0
  92. package/dist/session/protocol.d.ts +209 -0
  93. package/dist/session/protocol.d.ts.map +1 -0
  94. package/dist/session/protocol.js +75 -0
  95. package/dist/session/protocol.js.map +1 -0
  96. package/dist/session/response-handler.d.ts +48 -0
  97. package/dist/session/response-handler.d.ts.map +1 -0
  98. package/dist/session/response-handler.js +121 -0
  99. package/dist/session/response-handler.js.map +1 -0
  100. package/dist/session/sepa-accounts.d.ts +34 -0
  101. package/dist/session/sepa-accounts.d.ts.map +1 -0
  102. package/dist/session/sepa-accounts.js +96 -0
  103. package/dist/session/sepa-accounts.js.map +1 -0
  104. package/dist/session/session-setup.d.ts +72 -0
  105. package/dist/session/session-setup.d.ts.map +1 -0
  106. package/dist/session/session-setup.js +160 -0
  107. package/dist/session/session-setup.js.map +1 -0
  108. package/dist/session/session-state.d.ts +47 -0
  109. package/dist/session/session-state.d.ts.map +1 -0
  110. package/dist/session/session-state.js +147 -0
  111. package/dist/session/session-state.js.map +1 -0
  112. package/dist/session/tan-selection.d.ts +88 -0
  113. package/dist/session/tan-selection.d.ts.map +1 -0
  114. package/dist/session/tan-selection.js +178 -0
  115. package/dist/session/tan-selection.js.map +1 -0
  116. package/dist/session/user-prompts.d.ts +61 -0
  117. package/dist/session/user-prompts.d.ts.map +1 -0
  118. package/dist/session/user-prompts.js +164 -0
  119. package/dist/session/user-prompts.js.map +1 -0
  120. package/dist/tan/challenge.d.ts +114 -0
  121. package/dist/tan/challenge.d.ts.map +1 -0
  122. package/dist/tan/challenge.js +185 -0
  123. package/dist/tan/challenge.js.map +1 -0
  124. package/dist/tan/flicker.d.ts +36 -0
  125. package/dist/tan/flicker.d.ts.map +1 -0
  126. package/dist/tan/flicker.js +262 -0
  127. package/dist/tan/flicker.js.map +1 -0
  128. package/dist/tan/tan-image.d.ts +21 -0
  129. package/dist/tan/tan-image.d.ts.map +1 -0
  130. package/dist/tan/tan-image.js +41 -0
  131. package/dist/tan/tan-image.js.map +1 -0
  132. package/dist/tan/tan-models.d.ts +145 -0
  133. package/dist/tan/tan-models.d.ts.map +1 -0
  134. package/dist/tan/tan-models.js +148 -0
  135. package/dist/tan/tan-models.js.map +1 -0
  136. package/dist/util/async.d.ts +24 -0
  137. package/dist/util/async.d.ts.map +1 -0
  138. package/dist/util/async.js +49 -0
  139. package/dist/util/async.js.map +1 -0
  140. package/dist/util/bytes.d.ts +23 -0
  141. package/dist/util/bytes.d.ts.map +1 -0
  142. package/dist/util/bytes.js +136 -0
  143. package/dist/util/bytes.js.map +1 -0
  144. package/dist/util/call-context.d.ts +12 -0
  145. package/dist/util/call-context.d.ts.map +1 -0
  146. package/dist/util/call-context.js +29 -0
  147. package/dist/util/call-context.js.map +1 -0
  148. package/dist/util/dates.d.ts +62 -0
  149. package/dist/util/dates.d.ts.map +1 -0
  150. package/dist/util/dates.js +169 -0
  151. package/dist/util/dates.js.map +1 -0
  152. package/dist/util/errors.d.ts +9 -0
  153. package/dist/util/errors.d.ts.map +1 -0
  154. package/dist/util/errors.js +15 -0
  155. package/dist/util/errors.js.map +1 -0
  156. package/dist/util/immutable-map.d.ts +16 -0
  157. package/dist/util/immutable-map.d.ts.map +1 -0
  158. package/dist/util/immutable-map.js +38 -0
  159. package/dist/util/immutable-map.js.map +1 -0
  160. package/dist/util/json.d.ts +13 -0
  161. package/dist/util/json.d.ts.map +1 -0
  162. package/dist/util/json.js +44 -0
  163. package/dist/util/json.js.map +1 -0
  164. package/dist/util/text.d.ts +20 -0
  165. package/dist/util/text.d.ts.map +1 -0
  166. package/dist/util/text.js +78 -0
  167. package/dist/util/text.js.map +1 -0
  168. package/dist/util/xml.d.ts +35 -0
  169. package/dist/util/xml.d.ts.map +1 -0
  170. package/dist/util/xml.js +183 -0
  171. package/dist/util/xml.js.map +1 -0
  172. package/dist/v3/account-extension.d.ts +25 -0
  173. package/dist/v3/account-extension.d.ts.map +1 -0
  174. package/dist/v3/account-extension.js +176 -0
  175. package/dist/v3/account-extension.js.map +1 -0
  176. package/dist/v3/client.d.ts +24 -0
  177. package/dist/v3/client.d.ts.map +1 -0
  178. package/dist/v3/client.js +16 -0
  179. package/dist/v3/client.js.map +1 -0
  180. package/dist/v3/dialog.d.ts +78 -0
  181. package/dist/v3/dialog.d.ts.map +1 -0
  182. package/dist/v3/dialog.js +138 -0
  183. package/dist/v3/dialog.js.map +1 -0
  184. package/dist/v3/message.d.ts +72 -0
  185. package/dist/v3/message.d.ts.map +1 -0
  186. package/dist/v3/message.js +259 -0
  187. package/dist/v3/message.js.map +1 -0
  188. package/dist/v3/parameters.d.ts +79 -0
  189. package/dist/v3/parameters.d.ts.map +1 -0
  190. package/dist/v3/parameters.js +396 -0
  191. package/dist/v3/parameters.js.map +1 -0
  192. package/dist/v3/protocol.d.ts +68 -0
  193. package/dist/v3/protocol.d.ts.map +1 -0
  194. package/dist/v3/protocol.js +263 -0
  195. package/dist/v3/protocol.js.map +1 -0
  196. package/dist/v3/segments.d.ts +89 -0
  197. package/dist/v3/segments.d.ts.map +1 -0
  198. package/dist/v3/segments.js +283 -0
  199. package/dist/v3/segments.js.map +1 -0
  200. package/dist/v3/syntax.d.ts +76 -0
  201. package/dist/v3/syntax.d.ts.map +1 -0
  202. package/dist/v3/syntax.js +301 -0
  203. package/dist/v3/syntax.js.map +1 -0
  204. package/package.json +63 -4
  205. package/src/core/account.ts +250 -0
  206. package/src/core/amount.ts +209 -0
  207. package/src/core/balance.ts +84 -0
  208. package/src/core/bank-info.ts +66 -0
  209. package/src/core/client.ts +149 -0
  210. package/src/core/config.ts +141 -0
  211. package/src/core/errors.ts +203 -0
  212. package/src/core/feedback.ts +137 -0
  213. package/src/core/transaction.ts +156 -0
  214. package/src/core/transport.ts +114 -0
  215. package/src/formats/camt.ts +169 -0
  216. package/src/formats/mt940.ts +333 -0
  217. package/src/formats/readers.ts +56 -0
  218. package/src/formats/sepa-purpose.ts +75 -0
  219. package/src/index.ts +68 -0
  220. package/src/session/app-approval.ts +265 -0
  221. package/src/session/bank-connection.ts +51 -0
  222. package/src/session/dialog-runner.ts +119 -0
  223. package/src/session/login-guard.ts +135 -0
  224. package/src/session/parameter-data.ts +137 -0
  225. package/src/session/pin-tan-client.ts +186 -0
  226. package/src/session/pin-tan-dialog.ts +160 -0
  227. package/src/session/protocol.ts +311 -0
  228. package/src/session/response-handler.ts +130 -0
  229. package/src/session/sepa-accounts.ts +97 -0
  230. package/src/session/session-setup.ts +165 -0
  231. package/src/session/session-state.ts +170 -0
  232. package/src/session/tan-selection.ts +192 -0
  233. package/src/session/user-prompts.ts +174 -0
  234. package/src/tan/challenge.ts +252 -0
  235. package/src/tan/flicker.ts +270 -0
  236. package/src/tan/tan-image.ts +36 -0
  237. package/src/tan/tan-models.ts +247 -0
  238. package/src/util/async.ts +53 -0
  239. package/src/util/bytes.ts +135 -0
  240. package/src/util/call-context.ts +40 -0
  241. package/src/util/dates.ts +193 -0
  242. package/src/util/errors.ts +16 -0
  243. package/src/util/immutable-map.ts +47 -0
  244. package/src/util/json.ts +51 -0
  245. package/src/util/text.ts +82 -0
  246. package/src/util/xml.ts +172 -0
  247. package/src/v3/account-extension.ts +190 -0
  248. package/src/v3/client.ts +29 -0
  249. package/src/v3/dialog.ts +199 -0
  250. package/src/v3/message.ts +321 -0
  251. package/src/v3/parameters.ts +451 -0
  252. package/src/v3/protocol.ts +331 -0
  253. package/src/v3/segments.ts +331 -0
  254. package/src/v3/syntax.ts +307 -0
@@ -0,0 +1,88 @@
1
+ import { TanMethod, type TanMedium } from '../tan/tan-models.js';
2
+ import { type BankResponse, type PinTanProtocol, type ProtocolDialog } from './protocol.js';
3
+ import type { SessionState } from './session-state.js';
4
+ import type { UserPrompts } from './user-prompts.js';
5
+ /**
6
+ * The TAN method and medium the session's messages are signed with, chosen by the user among what the bank offers and
7
+ * the user may use, and kept in the session state.
8
+ */
9
+ export declare class TanSelection<R extends BankResponse, O> {
10
+ private readonly protocol;
11
+ private readonly state;
12
+ private readonly prompts;
13
+ /** TAN methods whose media were looked up in this session. A lookup is not repeated, even where it gave no medium. */
14
+ private readonly mediaLookedUp;
15
+ /** The list the last lookup gave, until `takeLookedUpMedia` hands it out. */
16
+ private lookedUpMedia;
17
+ /** Whether the bank refused a login signed with the one-step method in this session. */
18
+ private oneStepRefused;
19
+ constructor(protocol: PinTanProtocol<R, O>, state: SessionState, prompts: UserPrompts);
20
+ /** The TAN method in use; the one-step method until one is chosen. */
21
+ get method(): TanMethod;
22
+ /** Switches to `securityFunction` and `tanMedium` for the dialogs to come. */
23
+ select(securityFunction: string, tanMedium: string | undefined): void;
24
+ /**
25
+ * A dialog signed with the TAN method in use and its medium.
26
+ *
27
+ * Throws `FinTsUnsupportedError` if the method needs a medium the user has not chosen: the bank would refuse the
28
+ * login, and the client would not send the PIN again.
29
+ */
30
+ newDialog(): ProtocolDialog<R, O>;
31
+ /**
32
+ * The dialog that looks up the TAN media, signed with the TAN method in use.
33
+ *
34
+ * It runs before the medium is known, so it names a placeholder where the method needs one; the bank ignores the
35
+ * medium in this dialog (PIN/TAN B.4.3.1.3).
36
+ */
37
+ lookupDialog(): ProtocolDialog<R, O>;
38
+ /**
39
+ * The synchronization dialog. It runs before the TAN media are looked up, so its method must do without a medium the
40
+ * user has not chosen: the placeholder for one is meant for the lookup only (PIN/TAN B.4.3.1.3). The first method
41
+ * that does signs it:
42
+ * 1. the TAN method in use;
43
+ * 2. the one-step method, as for a user whose methods are not known yet (PIN/TAN B.4.3.1), unless the bank has refused
44
+ * a one-step login;
45
+ * 3. another two-step method the user may use.
46
+ *
47
+ * Throws `FinTsUnsupportedError` if none does, before the bank could refuse the login.
48
+ */
49
+ synchronizationDialog(): ProtocolDialog<R, O>;
50
+ /** Whether `method` needs a medium the user has not chosen. */
51
+ private lacksMedium;
52
+ /**
53
+ * The two-step TAN methods the bank offers, the user may use and this client can run; the one-step method if there
54
+ * are none.
55
+ *
56
+ * Throws `FinTsUnsupportedError` if the bank offers the user nothing but methods the client cannot run.
57
+ */
58
+ available(): TanMethod[];
59
+ /**
60
+ * Stops using `rejected`, the method of a login the bank refused; returns whether another available method is left.
61
+ *
62
+ * The user chooses that method, unless the one in use is still available: a refused one-step synchronization does
63
+ * not rule out the method the user chose before.
64
+ */
65
+ replace(rejected: TanMethod): Promise<boolean>;
66
+ /** Keeps the chosen TAN method if it is still available, otherwise lets the user choose. */
67
+ ensureMethodChosen(): Promise<void>;
68
+ /**
69
+ * Whether the media of the method in use have to be looked up: it needs a medium the user has not chosen, and they
70
+ * were not looked up for it in this session.
71
+ */
72
+ get mediumToLookUp(): boolean;
73
+ /**
74
+ * Lets the user choose the medium of the method in use among the active ones in `media`, the result of a lookup;
75
+ * none where the lookup gave no list or no active medium.
76
+ */
77
+ chooseMedium(media: TanMedium[] | undefined): Promise<void>;
78
+ /**
79
+ * The list of the last lookup, once; `undefined` if there was none since the last time.
80
+ *
81
+ * `getTanMedia` takes it, so that the list is not asked for twice in a row. It also outlasts a call that failed for
82
+ * want of an active medium, so that the app can show the user the list that tells why; later calls ask anew.
83
+ */
84
+ takeLookedUpMedia(): TanMedium[] | undefined;
85
+ /** The name of the medium the user chooses among the active ones in `media`; `undefined` if none is active. */
86
+ private chooseMediumOf;
87
+ }
88
+ //# sourceMappingURL=tan-selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tan-selection.d.ts","sourceRoot":"","sources":["../../src/session/tan-selection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAe,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;GAGG;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;IAZ1B,sHAAsH;IACtH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,6EAA6E;IAC7E,OAAO,CAAC,aAAa,CAA0B;IAE/C,wFAAwF;IACxF,OAAO,CAAC,cAAc,CAAS;gBAGZ,QAAQ,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAC9B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW;IAGvC,sEAAsE;IACtE,IAAI,MAAM,IAAI,SAAS,CAItB;IAED,8EAA8E;IAC9E,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKrE;;;;;OAKG;IACH,SAAS,IAAI,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAYjC;;;;;OAKG;IACH,YAAY,IAAI,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAKpC;;;;;;;;;;OAUG;IACH,qBAAqB,IAAI,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAY7C,+DAA+D;IAC/D,OAAO,CAAC,WAAW;IAInB;;;;;OAKG;IACH,SAAS,IAAI,SAAS,EAAE;IAgBxB;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IASpD,4FAA4F;IACtF,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQzC;;;OAGG;IACH,IAAI,cAAc,IAAI,OAAO,CAG5B;IAED;;;OAGG;IACG,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE;;;;;OAKG;IACH,iBAAiB,IAAI,SAAS,EAAE,GAAG,SAAS;IAM5C,+GAA+G;YACjG,cAAc;CAQ7B"}
@@ -0,0 +1,178 @@
1
+ import { FinTsUnsupportedError } from '../core/errors.js';
2
+ import { TanMethod } from '../tan/tan-models.js';
3
+ import { noReference } from './protocol.js';
4
+ /**
5
+ * The TAN method and medium the session's messages are signed with, chosen by the user among what the bank offers and
6
+ * the user may use, and kept in the session state.
7
+ */
8
+ export class TanSelection {
9
+ protocol;
10
+ state;
11
+ prompts;
12
+ /** TAN methods whose media were looked up in this session. A lookup is not repeated, even where it gave no medium. */
13
+ mediaLookedUp = new Set();
14
+ /** The list the last lookup gave, until `takeLookedUpMedia` hands it out. */
15
+ lookedUpMedia;
16
+ /** Whether the bank refused a login signed with the one-step method in this session. */
17
+ oneStepRefused = false;
18
+ constructor(protocol, state, prompts) {
19
+ this.protocol = protocol;
20
+ this.state = state;
21
+ this.prompts = prompts;
22
+ }
23
+ /** The TAN method in use; the one-step method until one is chosen. */
24
+ get method() {
25
+ const code = this.state.tanMethod;
26
+ if (code === undefined || code === TanMethod.oneStep.securityFunction)
27
+ return TanMethod.oneStep;
28
+ return this.protocol.bankParameters?.tanMethods.find((m) => m.securityFunction === code) ?? TanMethod.oneStep;
29
+ }
30
+ /** Switches to `securityFunction` and `tanMedium` for the dialogs to come. */
31
+ select(securityFunction, tanMedium) {
32
+ this.state.useTanMethod(securityFunction, tanMedium);
33
+ this.mediaLookedUp.delete(securityFunction);
34
+ }
35
+ /**
36
+ * A dialog signed with the TAN method in use and its medium.
37
+ *
38
+ * Throws `FinTsUnsupportedError` if the method needs a medium the user has not chosen: the bank would refuse the
39
+ * login, and the client would not send the PIN again.
40
+ */
41
+ newDialog() {
42
+ const method = this.method;
43
+ if (this.lacksMedium(method)) {
44
+ throw new FinTsUnsupportedError(`The TAN method ${method.name} needs a TAN medium, and the client could not learn one: the bank lists no ` +
45
+ 'active medium for it, or does not offer or permit the list of TAN media, or rejected it. Pass a medium to ' +
46
+ 'selectTanMethod, or choose another method');
47
+ }
48
+ return this.protocol.newDialog(method, this.state.tanMedium);
49
+ }
50
+ /**
51
+ * The dialog that looks up the TAN media, signed with the TAN method in use.
52
+ *
53
+ * It runs before the medium is known, so it names a placeholder where the method needs one; the bank ignores the
54
+ * medium in this dialog (PIN/TAN B.4.3.1.3).
55
+ */
56
+ lookupDialog() {
57
+ const method = this.method;
58
+ return this.protocol.newDialog(method, this.lacksMedium(method) ? noReference : this.state.tanMedium);
59
+ }
60
+ /**
61
+ * The synchronization dialog. It runs before the TAN media are looked up, so its method must do without a medium the
62
+ * user has not chosen: the placeholder for one is meant for the lookup only (PIN/TAN B.4.3.1.3). The first method
63
+ * that does signs it:
64
+ * 1. the TAN method in use;
65
+ * 2. the one-step method, as for a user whose methods are not known yet (PIN/TAN B.4.3.1), unless the bank has refused
66
+ * a one-step login;
67
+ * 3. another two-step method the user may use.
68
+ *
69
+ * Throws `FinTsUnsupportedError` if none does, before the bank could refuse the login.
70
+ */
71
+ synchronizationDialog() {
72
+ const method = this.method;
73
+ if (!this.lacksMedium(method))
74
+ return this.protocol.newDialog(method, this.state.tanMedium);
75
+ if (!this.oneStepRefused)
76
+ return this.protocol.newDialog(TanMethod.oneStep);
77
+ const other = this.available().find((m) => !m.isOneStep && !this.lacksMedium(m));
78
+ if (other !== undefined)
79
+ return this.protocol.newDialog(other);
80
+ throw new FinTsUnsupportedError(`The bank refuses the one-step method, and the TAN method ${method.name} needs a TAN medium, which the client ` +
81
+ 'can look up only after the synchronization. Pass the medium to selectTanMethod, or choose another method');
82
+ }
83
+ /** Whether `method` needs a medium the user has not chosen. */
84
+ lacksMedium(method) {
85
+ return this.state.tanMedium === undefined && needsMediumChoice(method);
86
+ }
87
+ /**
88
+ * The two-step TAN methods the bank offers, the user may use and this client can run; the one-step method if there
89
+ * are none.
90
+ *
91
+ * Throws `FinTsUnsupportedError` if the bank offers the user nothing but methods the client cannot run.
92
+ */
93
+ available() {
94
+ const bpd = this.protocol.bankParameters;
95
+ if (bpd === undefined)
96
+ return [TanMethod.oneStep];
97
+ const allowed = this.state.allowedMethods ?? this.protocol.userParameters?.allowedTanMethods;
98
+ const isAllowed = (securityFunction) => allowed === undefined || allowed.length === 0 || allowed.includes(securityFunction);
99
+ const runnable = bpd.tanMethods.filter((m) => isAllowed(m.securityFunction));
100
+ if (runnable.length === 0 && bpd.unsupportedTanMethods.some(isAllowed)) {
101
+ throw new FinTsUnsupportedError('The bank offers only TAN methods this client cannot run: process variant 1, or methods that need an SMS ' +
102
+ 'charge account or an HHD_UC answer');
103
+ }
104
+ return runnable.length === 0 ? [TanMethod.oneStep] : runnable;
105
+ }
106
+ /**
107
+ * Stops using `rejected`, the method of a login the bank refused; returns whether another available method is left.
108
+ *
109
+ * The user chooses that method, unless the one in use is still available: a refused one-step synchronization does
110
+ * not rule out the method the user chose before.
111
+ */
112
+ async replace(rejected) {
113
+ if (rejected.isOneStep)
114
+ this.oneStepRefused = true;
115
+ const others = this.available().filter((m) => m.securityFunction !== rejected.securityFunction);
116
+ if (others.some((m) => m.securityFunction === this.state.tanMethod))
117
+ return true;
118
+ if (others.length === 0)
119
+ return false;
120
+ this.state.useTanMethod((await this.prompts.chooseMethod(others)).securityFunction);
121
+ return true;
122
+ }
123
+ /** Keeps the chosen TAN method if it is still available, otherwise lets the user choose. */
124
+ async ensureMethodChosen() {
125
+ const candidates = this.available();
126
+ const method = candidates.find((m) => m.securityFunction === this.state.tanMethod) ??
127
+ (await this.prompts.chooseMethod(candidates));
128
+ if (method.securityFunction !== this.state.tanMethod)
129
+ this.state.useTanMethod(method.securityFunction);
130
+ }
131
+ /**
132
+ * Whether the media of the method in use have to be looked up: it needs a medium the user has not chosen, and they
133
+ * were not looked up for it in this session.
134
+ */
135
+ get mediumToLookUp() {
136
+ const method = this.method;
137
+ return this.lacksMedium(method) && !this.mediaLookedUp.has(method.securityFunction);
138
+ }
139
+ /**
140
+ * Lets the user choose the medium of the method in use among the active ones in `media`, the result of a lookup;
141
+ * none where the lookup gave no list or no active medium.
142
+ */
143
+ async chooseMedium(media) {
144
+ const method = this.method;
145
+ this.lookedUpMedia = media;
146
+ this.state.useTanMedium(media === undefined ? undefined : await this.chooseMediumOf(method, media));
147
+ this.mediaLookedUp.add(method.securityFunction);
148
+ }
149
+ /**
150
+ * The list of the last lookup, once; `undefined` if there was none since the last time.
151
+ *
152
+ * `getTanMedia` takes it, so that the list is not asked for twice in a row. It also outlasts a call that failed for
153
+ * want of an active medium, so that the app can show the user the list that tells why; later calls ask anew.
154
+ */
155
+ takeLookedUpMedia() {
156
+ const media = this.lookedUpMedia;
157
+ this.lookedUpMedia = undefined;
158
+ return media;
159
+ }
160
+ /** The name of the medium the user chooses among the active ones in `media`; `undefined` if none is active. */
161
+ async chooseMediumOf(method, media) {
162
+ const active = media.filter((m) => m.isActive && m.name !== undefined);
163
+ // HITAB version 5 names the method each medium belongs to; a medium of another method would not do.
164
+ const ofMethod = active.filter((m) => m.securityFunction === method.securityFunction);
165
+ const candidates = ofMethod.length === 0 ? active : ofMethod;
166
+ if (candidates.length === 0)
167
+ return undefined;
168
+ return (await this.prompts.chooseMedium(candidates)).name;
169
+ }
170
+ }
171
+ /**
172
+ * Whether messages signed with `method` must name the TAN medium: the method requires the name, and the user may have
173
+ * several media (PIN/TAN, HKTAN "Bezeichnung des TAN-Mediums").
174
+ */
175
+ function needsMediumChoice(method) {
176
+ return method.needsMediumName && (method.activeMediaCount ?? 0) > 1;
177
+ }
178
+ //# sourceMappingURL=tan-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tan-selection.js","sourceRoot":"","sources":["../../src/session/tan-selection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type { BankMessage } from '../core/bank-info.js';
2
+ import type { FinTsClientOptions, MessageLogger } from '../core/client.js';
3
+ import type { FinTsFeedback } from '../core/feedback.js';
4
+ import type { TanAnswer, TanChallenge } from '../tan/challenge.js';
5
+ import type { TanMedium, TanMethod } from '../tan/tan-models.js';
6
+ /**
7
+ * Everything a session tells the app, asks of it or waits for: the bank's messages, warnings and log, the TAN callback,
8
+ * the selectors and the pauses between status requests.
9
+ *
10
+ * Once the client is closed nothing is told or asked, and every wait ends with `FinTsStateError`. Errors of the
11
+ * callbacks that only inform the app wait for `reportingCallbackErrors`, as `FinTsClientOptions` promises.
12
+ */
13
+ export declare class UserPrompts {
14
+ private readonly options;
15
+ private closed;
16
+ /** The first error an informing callback threw during the running call. */
17
+ private callbackError;
18
+ /** Aborts the waits under way; each wait removes its abort when it is over. */
19
+ private readonly aborts;
20
+ constructor(options: FinTsClientOptions);
21
+ /** Ends every wait; the client calls it once. */
22
+ close(): void;
23
+ /** Throws `FinTsStateError` once `close` was called. */
24
+ checkOpen(): void;
25
+ /**
26
+ * Runs `call` and then fails it with the first error an informing callback threw meanwhile; an error of `call` itself
27
+ * takes precedence.
28
+ */
29
+ reportingCallbackErrors<T>(call: () => Promise<T>): Promise<T>;
30
+ /** The app's logger, whose errors are kept for `reportingCallbackErrors`; `undefined` without one. */
31
+ get logger(): MessageLogger | undefined;
32
+ /** Passes the bank's `message` to the app, unless the client is closed. */
33
+ showBankMessage(message: BankMessage): void;
34
+ /** Passes the bank's `warning` to the app, unless the client is closed. */
35
+ showWarning(warning: FinTsFeedback): void;
36
+ private inform;
37
+ /** Shows `challenge` through the TAN callback and returns its answer. */
38
+ askTan(challenge: TanChallenge): Promise<TanAnswer>;
39
+ /** Waits for `delayMs` milliseconds, or until `interrupt` settles. */
40
+ pause(delayMs: number, interrupt?: Promise<unknown>): Promise<void>;
41
+ /**
42
+ * The TAN method to use among `candidates`: the app's choice, or the first without a selector or an answer.
43
+ *
44
+ * Throws `TypeError` if the selector returns a method that is not among `candidates`.
45
+ */
46
+ chooseMethod(candidates: readonly TanMethod[]): Promise<TanMethod>;
47
+ /**
48
+ * The TAN medium to use among the active `media`: the app's choice, or the first without a selector or an answer.
49
+ *
50
+ * Throws `TypeError` if the selector returns a medium that is not among `media`.
51
+ */
52
+ chooseMedium(media: readonly TanMedium[]): Promise<TanMedium>;
53
+ /**
54
+ * Starts `wait` and ends it with `FinTsStateError` if `close` is called before it is over.
55
+ *
56
+ * Once the client is closed, the returned promise rejects rather than this function throwing: a caller that starts
57
+ * several waits at once would otherwise leave the failure of those started first unheard.
58
+ */
59
+ private unlessClosed;
60
+ }
61
+ //# sourceMappingURL=user-prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prompts.d.ts","sourceRoot":"","sources":["../../src/session/user-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQjE;;;;;;GAMG;AACH,qBAAa,WAAW;IASV,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,MAAM,CAAS;IAEvB,2EAA2E;IAC3E,OAAO,CAAC,aAAa,CAAiC;IAEtD,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAEnB,OAAO,EAAE,kBAAkB;IAExD,iDAAiD;IACjD,KAAK,IAAI,IAAI;IAMb,wDAAwD;IACxD,SAAS,IAAI,IAAI;IAIjB;;;OAGG;IACG,uBAAuB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASpE,sGAAsG;IACtG,IAAI,MAAM,IAAI,aAAa,GAAG,SAAS,CAQtC;IAED,2EAA2E;IAC3E,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAS3C,2EAA2E;IAC3E,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IASzC,OAAO,CAAC,MAAM;IAQd,yEAAyE;IACzE,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC;IAInD,sEAAsE;IACtE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnE;;;;OAIG;IACG,YAAY,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAUxE;;;;OAIG;IACG,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAUnE;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAsBrB"}
@@ -0,0 +1,164 @@
1
+ import { FinTsStateError } from '../core/errors.js';
2
+ import { Deferred } from '../util/async.js';
3
+ import { invalidArgument } from '../util/errors.js';
4
+ function closedError() {
5
+ return new FinTsStateError('The FinTS client is closed');
6
+ }
7
+ /**
8
+ * Everything a session tells the app, asks of it or waits for: the bank's messages, warnings and log, the TAN callback,
9
+ * the selectors and the pauses between status requests.
10
+ *
11
+ * Once the client is closed nothing is told or asked, and every wait ends with `FinTsStateError`. Errors of the
12
+ * callbacks that only inform the app wait for `reportingCallbackErrors`, as `FinTsClientOptions` promises.
13
+ */
14
+ export class UserPrompts {
15
+ options;
16
+ closed = false;
17
+ /** The first error an informing callback threw during the running call. */
18
+ callbackError;
19
+ /** Aborts the waits under way; each wait removes its abort when it is over. */
20
+ aborts = new Set();
21
+ constructor(options) {
22
+ this.options = options;
23
+ }
24
+ /** Ends every wait; the client calls it once. */
25
+ close() {
26
+ this.closed = true;
27
+ for (const abort of [...this.aborts])
28
+ abort();
29
+ this.aborts.clear();
30
+ }
31
+ /** Throws `FinTsStateError` once `close` was called. */
32
+ checkOpen() {
33
+ if (this.closed)
34
+ throw closedError();
35
+ }
36
+ /**
37
+ * Runs `call` and then fails it with the first error an informing callback threw meanwhile; an error of `call` itself
38
+ * takes precedence.
39
+ */
40
+ async reportingCallbackErrors(call) {
41
+ this.callbackError = undefined;
42
+ const result = await call();
43
+ // Set by a callback while `call` ran, which the compiler cannot see.
44
+ const failure = this.callbackError;
45
+ if (failure !== undefined)
46
+ throw failure.error;
47
+ return result;
48
+ }
49
+ /** The app's logger, whose errors are kept for `reportingCallbackErrors`; `undefined` without one. */
50
+ get logger() {
51
+ const logger = this.options.logger;
52
+ if (logger === undefined)
53
+ return undefined;
54
+ return (direction, message) => {
55
+ this.inform(() => {
56
+ logger(direction, message);
57
+ });
58
+ };
59
+ }
60
+ /** Passes the bank's `message` to the app, unless the client is closed. */
61
+ showBankMessage(message) {
62
+ const handler = this.options.onBankMessage;
63
+ if (handler !== undefined && !this.closed) {
64
+ this.inform(() => {
65
+ handler(message);
66
+ });
67
+ }
68
+ }
69
+ /** Passes the bank's `warning` to the app, unless the client is closed. */
70
+ showWarning(warning) {
71
+ const handler = this.options.onWarning;
72
+ if (handler !== undefined && !this.closed) {
73
+ this.inform(() => {
74
+ handler(warning);
75
+ });
76
+ }
77
+ }
78
+ inform(callback) {
79
+ try {
80
+ callback();
81
+ }
82
+ catch (error) {
83
+ this.callbackError ??= { error };
84
+ }
85
+ }
86
+ /** Shows `challenge` through the TAN callback and returns its answer. */
87
+ askTan(challenge) {
88
+ return this.unlessClosed(() => this.options.tanCallback(challenge));
89
+ }
90
+ /** Waits for `delayMs` milliseconds, or until `interrupt` settles. */
91
+ pause(delayMs, interrupt) {
92
+ if (this.closed)
93
+ return Promise.reject(closedError());
94
+ let timer;
95
+ const elapsed = new Promise((resolve) => {
96
+ timer = setTimeout(resolve, Math.max(0, delayMs));
97
+ });
98
+ // Neither an interrupted wait nor a closed client may leave a timer behind that keeps the process alive.
99
+ return this.unlessClosed(() => Promise.race([elapsed, ...(interrupt === undefined ? [] : [interrupt.then(() => undefined)])])).finally(() => {
100
+ clearTimeout(timer);
101
+ });
102
+ }
103
+ /**
104
+ * The TAN method to use among `candidates`: the app's choice, or the first without a selector or an answer.
105
+ *
106
+ * Throws `TypeError` if the selector returns a method that is not among `candidates`.
107
+ */
108
+ async chooseMethod(candidates) {
109
+ const selector = this.options.tanMethodSelector;
110
+ if (candidates.length === 1 || selector === undefined)
111
+ return candidates[0];
112
+ const chosen = await this.unlessClosed(() => selector(candidates));
113
+ if (chosen === undefined)
114
+ return candidates[0];
115
+ const match = candidates.find((m) => m.securityFunction === chosen.securityFunction);
116
+ if (match === undefined)
117
+ throw invalidArgument('Returned a TAN method the bank did not offer', 'tanMethodSelector');
118
+ return match;
119
+ }
120
+ /**
121
+ * The TAN medium to use among the active `media`: the app's choice, or the first without a selector or an answer.
122
+ *
123
+ * Throws `TypeError` if the selector returns a medium that is not among `media`.
124
+ */
125
+ async chooseMedium(media) {
126
+ const selector = this.options.tanMediumSelector;
127
+ if (media.length === 1 || selector === undefined)
128
+ return media[0];
129
+ const chosen = await this.unlessClosed(() => selector(media));
130
+ if (chosen === undefined)
131
+ return media[0];
132
+ const match = media.find((m) => m.name === chosen.name);
133
+ if (match === undefined)
134
+ throw invalidArgument('Returned a TAN medium the bank did not list', 'tanMediumSelector');
135
+ return match;
136
+ }
137
+ /**
138
+ * Starts `wait` and ends it with `FinTsStateError` if `close` is called before it is over.
139
+ *
140
+ * Once the client is closed, the returned promise rejects rather than this function throwing: a caller that starts
141
+ * several waits at once would otherwise leave the failure of those started first unheard.
142
+ */
143
+ unlessClosed(wait) {
144
+ if (this.closed)
145
+ return Promise.reject(closedError());
146
+ const result = new Deferred();
147
+ const abort = () => {
148
+ result.reject(closedError());
149
+ };
150
+ this.aborts.add(abort);
151
+ // Runs `wait` at once, as far as its first `await`, and turns an error it throws into a rejection.
152
+ const started = (async () => wait())();
153
+ started
154
+ .then((value) => {
155
+ result.resolve(value);
156
+ }, (error) => {
157
+ result.reject(error);
158
+ })
159
+ .finally(() => this.aborts.delete(abort))
160
+ .catch(() => undefined);
161
+ return result.promise;
162
+ }
163
+ }
164
+ //# sourceMappingURL=user-prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prompts.js","sourceRoot":"","sources":["../../src/session/user-prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { FlickerCode } from './flicker.js';
2
+ import { TanImage } from './tan-image.js';
3
+ import type { TanMedium, TanMethod } from './tan-models.js';
4
+ /** `message`, or `undefined` where it is empty or the filler banks send when there is nothing to show. */
5
+ export declare function challengeText(message: string | undefined): string | undefined;
6
+ /** What `TanChallenge` takes. */
7
+ export interface TanChallengeInit {
8
+ method: TanMethod;
9
+ reference: string;
10
+ message?: string | undefined;
11
+ hhdUc?: Uint8Array | undefined;
12
+ flickerCode?: FlickerCode | undefined;
13
+ image?: TanImage | undefined;
14
+ isDecoupled?: boolean;
15
+ validUntil?: Date | undefined;
16
+ tanMediumName?: string | undefined;
17
+ attempt?: number;
18
+ resolved?: Promise<void> | undefined;
19
+ }
20
+ /** A request from the bank to authorize an action with a TAN or an app approval. */
21
+ export declare class TanChallenge {
22
+ /** The TAN method the challenge is for. */
23
+ readonly method: TanMethod;
24
+ /** Bank reference of the pending action. */
25
+ readonly reference: string;
26
+ /** Challenge text as sent by the bank; may contain simple HTML. See `plainMessage`. */
27
+ readonly message: string | undefined;
28
+ /** Raw challenge data for TAN generators (HHD_UC). */
29
+ readonly hhdUc: Uint8Array | undefined;
30
+ /** chipTAN optical flicker code, if the challenge contains one. */
31
+ readonly flickerCode: FlickerCode | undefined;
32
+ /** photoTAN / QR-TAN image, if the challenge contains one. */
33
+ readonly image: TanImage | undefined;
34
+ /** Approval happens in a separate app; see `TanCallback` for what to answer. */
35
+ readonly isDecoupled: boolean;
36
+ /** The exact moment until which the bank accepts the TAN or the approval, where it states date and time of day. */
37
+ readonly validUntil: Date | undefined;
38
+ /** Name of the TAN medium the bank sent the challenge to. */
39
+ readonly tanMediumName: string | undefined;
40
+ /** Counts repeated prompts for the same decoupled approval. */
41
+ readonly attempt: number;
42
+ /**
43
+ * Settles when the client needs no more answer to this challenge: the bank confirmed the approval, or the approval
44
+ * failed, timed out or was cancelled. Set where the client asks the bank by itself while the callback shows the
45
+ * challenge (`TanCallback`), `undefined` otherwise. It never rejects.
46
+ */
47
+ readonly resolved: Promise<void> | undefined;
48
+ /** A challenge as the bank sent it. Use `TanChallenge.create` to have a flicker code or image detected in the data. */
49
+ constructor(init: TanChallengeInit);
50
+ /** Builds a challenge and detects a photoTAN image or chipTAN flicker code in `hhdUc` or `message`. */
51
+ static create(init: Omit<TanChallengeInit, 'flickerCode' | 'image' | 'resolved'>): TanChallenge;
52
+ /**
53
+ * Whether the user can report the approval in the banking app; `false` where only the bank's confirmation completes
54
+ * it, which `TanCallback` tells how to handle.
55
+ */
56
+ get manualConfirmation(): boolean;
57
+ /**
58
+ * `message` as the user reads it.
59
+ *
60
+ * A method with structured challenges (`TanMethod.structuredChallenge`) may use the formatting tags the specification
61
+ * defines. Line breaks, paragraphs and list items become new lines. Bold, italics, underlining and list tags are
62
+ * removed, and the entity references of such markup are resolved. Any other challenge stays as the bank sent it,
63
+ * which is how the specification wants it shown.
64
+ */
65
+ get plainMessage(): string | undefined;
66
+ }
67
+ /** `challenge` again, counted as the next prompt for the same approval, with the bank's new instructions `message`. */
68
+ export declare function nextAttempt(challenge: TanChallenge, message?: string): TanChallenge;
69
+ /** `challenge` with `TanChallenge.resolved` set to `resolved`. */
70
+ export declare function withResolved(challenge: TanChallenge, resolved: Promise<void>): TanChallenge;
71
+ /** The user's answer to a `TanChallenge`: `TanAnswer.tan(…)`, `TanAnswer.approved` or `TanAnswer.cancelled`. */
72
+ export type TanAnswer =
73
+ /** The TAN the user entered; an empty one cancels. */
74
+ {
75
+ readonly kind: 'tan';
76
+ readonly tan: string;
77
+ }
78
+ /** The user reports the approval in the banking app (`TanChallenge.isDecoupled`); the client then asks the bank. */
79
+ | {
80
+ readonly kind: 'approved';
81
+ }
82
+ /** The user cancels: the client ends the bank dialog, and the call fails with `FinTsTanCancelledError`. */
83
+ | {
84
+ readonly kind: 'cancelled';
85
+ };
86
+ /** The answers a `TanCallback` returns. */
87
+ export declare const TanAnswer: Readonly<{
88
+ /** The TAN the user entered; an empty one cancels. */
89
+ tan: (tan: string) => TanAnswer;
90
+ /** The user reports the approval in the banking app (`TanChallenge.isDecoupled`); the client then asks the bank. */
91
+ approved: {
92
+ readonly kind: "approved";
93
+ };
94
+ /** The user cancels: the client ends the bank dialog, and the call fails with `FinTsTanCancelledError`. */
95
+ cancelled: {
96
+ readonly kind: "cancelled";
97
+ };
98
+ }>;
99
+ /**
100
+ * Shows the `TanChallenge` to the user and returns the `TanAnswer`: `TanAnswer.tan(…)` for a TAN, `TanAnswer.approved`
101
+ * once the user reports an approval in the banking app (`TanChallenge.isDecoupled`), `TanAnswer.cancelled` to cancel
102
+ * either. An answer that does not fit the challenge fails the call with a `TypeError`.
103
+ *
104
+ * Where the client polls the bank by itself, it sets `TanChallenge.resolved`: close the prompt when it settles, the
105
+ * callback's result is no longer waited for then. If the bank has not confirmed a reported approval yet, the callback is
106
+ * called again with the next `TanChallenge.attempt`. Where `TanChallenge.manualConfirmation` is `false`, offer no
107
+ * confirm button: any answer but `TanAnswer.cancelled` is ignored.
108
+ */
109
+ export type TanCallback = (challenge: TanChallenge) => TanAnswer | Promise<TanAnswer>;
110
+ /** Picks one of several allowed TAN methods; the first is used when this returns `undefined`. */
111
+ export type TanMethodSelector = (methods: readonly TanMethod[]) => TanMethod | undefined | Promise<TanMethod | undefined>;
112
+ /** Picks one of several active TAN media; the first is used when this returns `undefined`. */
113
+ export type TanMediumSelector = (media: readonly TanMedium[]) => TanMedium | undefined | Promise<TanMedium | undefined>;
114
+ //# sourceMappingURL=challenge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../src/tan/challenge.ts"],"names":[],"mappings":"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"}