@kreiseck/kasseneck-api 0.6.46 → 0.6.49

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 (102) hide show
  1. package/README.md +95 -15
  2. package/dist/cjs/client/aufrufe.d.ts +1 -1
  3. package/dist/cjs/client/aufrufe.js +1 -0
  4. package/dist/cjs/client/errors.d.ts +7 -1
  5. package/dist/cjs/client/errors.js +8 -1
  6. package/dist/cjs/client/receipts.d.ts +16 -0
  7. package/dist/cjs/client/receipts.js +10 -0
  8. package/dist/cjs/client/transport.js +5 -4
  9. package/dist/cjs/index.d.ts +1 -1
  10. package/dist/cjs/index.js +4 -2
  11. package/dist/cjs/models/cancellation.d.ts +22 -0
  12. package/dist/cjs/models/cancellation.js +31 -1
  13. package/dist/cjs/models/hobex-receipt.js +9 -2
  14. package/dist/cjs/models/index.d.ts +1 -1
  15. package/dist/cjs/models/index.js +3 -1
  16. package/dist/cjs/models/receipt.js +3 -0
  17. package/dist/cjs/models/voucher.js +18 -2
  18. package/dist/cjs/payments/hobex-hps/connect-client.d.ts +104 -0
  19. package/dist/cjs/payments/hobex-hps/connect-client.js +159 -0
  20. package/dist/cjs/payments/hobex-hps/errors.d.ts +122 -0
  21. package/dist/cjs/payments/hobex-hps/errors.js +158 -0
  22. package/dist/cjs/payments/hobex-hps/events.d.ts +22 -0
  23. package/dist/cjs/payments/hobex-hps/events.js +2 -0
  24. package/dist/cjs/payments/hobex-hps/index.d.ts +27 -0
  25. package/dist/cjs/payments/hobex-hps/index.js +66 -0
  26. package/dist/cjs/payments/hobex-hps/outcome.d.ts +31 -0
  27. package/dist/cjs/payments/hobex-hps/outcome.js +7 -0
  28. package/dist/cjs/payments/hobex-hps/payments.d.ts +149 -0
  29. package/dist/cjs/payments/hobex-hps/payments.js +550 -0
  30. package/dist/cjs/payments/hobex-hps/receipt.d.ts +28 -0
  31. package/dist/cjs/payments/hobex-hps/receipt.js +60 -0
  32. package/dist/cjs/payments/hobex-hps/transaction-id.d.ts +65 -0
  33. package/dist/cjs/payments/hobex-hps/transaction-id.js +91 -0
  34. package/dist/cjs/payments/hobex-hps/transaction-response.d.ts +163 -0
  35. package/dist/cjs/payments/hobex-hps/transaction-response.js +245 -0
  36. package/dist/cjs/payments/hobex.js +9 -6
  37. package/dist/cjs/payments/index.d.ts +26 -14
  38. package/dist/cjs/payments/index.js +59 -15
  39. package/dist/cjs/printing/index.d.ts +1 -1
  40. package/dist/cjs/printing/index.js +2 -1
  41. package/dist/cjs/printing/webusb.d.ts +37 -7
  42. package/dist/cjs/printing/webusb.js +76 -18
  43. package/dist/cjs/receipt/epos.d.ts +18 -0
  44. package/dist/cjs/receipt/epos.js +78 -6
  45. package/dist/cjs/receipt/index.d.ts +1 -1
  46. package/dist/cjs/receipt/index.js +2 -1
  47. package/dist/cjs/register/index.d.ts +1 -1
  48. package/dist/cjs/register/index.js +2 -1
  49. package/dist/cjs/register/pairing.d.ts +59 -0
  50. package/dist/cjs/register/pairing.js +51 -2
  51. package/dist/esm/client/aufrufe.d.ts +1 -1
  52. package/dist/esm/client/aufrufe.js +1 -0
  53. package/dist/esm/client/errors.d.ts +7 -1
  54. package/dist/esm/client/errors.js +8 -1
  55. package/dist/esm/client/receipts.d.ts +16 -0
  56. package/dist/esm/client/receipts.js +10 -0
  57. package/dist/esm/client/transport.js +5 -4
  58. package/dist/esm/index.d.ts +1 -1
  59. package/dist/esm/index.js +1 -1
  60. package/dist/esm/models/cancellation.d.ts +22 -0
  61. package/dist/esm/models/cancellation.js +29 -0
  62. package/dist/esm/models/hobex-receipt.js +10 -3
  63. package/dist/esm/models/index.d.ts +1 -1
  64. package/dist/esm/models/index.js +1 -1
  65. package/dist/esm/models/receipt.js +3 -0
  66. package/dist/esm/models/voucher.js +18 -2
  67. package/dist/esm/payments/hobex-hps/connect-client.d.ts +104 -0
  68. package/dist/esm/payments/hobex-hps/connect-client.js +156 -0
  69. package/dist/esm/payments/hobex-hps/errors.d.ts +122 -0
  70. package/dist/esm/payments/hobex-hps/errors.js +149 -0
  71. package/dist/esm/payments/hobex-hps/events.d.ts +22 -0
  72. package/dist/esm/payments/hobex-hps/events.js +1 -0
  73. package/dist/esm/payments/hobex-hps/index.d.ts +27 -0
  74. package/dist/esm/payments/hobex-hps/index.js +26 -0
  75. package/dist/esm/payments/hobex-hps/outcome.d.ts +31 -0
  76. package/dist/esm/payments/hobex-hps/outcome.js +4 -0
  77. package/dist/esm/payments/hobex-hps/payments.d.ts +149 -0
  78. package/dist/esm/payments/hobex-hps/payments.js +547 -0
  79. package/dist/esm/payments/hobex-hps/receipt.d.ts +28 -0
  80. package/dist/esm/payments/hobex-hps/receipt.js +57 -0
  81. package/dist/esm/payments/hobex-hps/transaction-id.d.ts +65 -0
  82. package/dist/esm/payments/hobex-hps/transaction-id.js +86 -0
  83. package/dist/esm/payments/hobex-hps/transaction-response.d.ts +163 -0
  84. package/dist/esm/payments/hobex-hps/transaction-response.js +233 -0
  85. package/dist/esm/payments/hobex.js +9 -6
  86. package/dist/esm/payments/index.d.ts +26 -14
  87. package/dist/esm/payments/index.js +26 -14
  88. package/dist/esm/printing/index.d.ts +1 -1
  89. package/dist/esm/printing/index.js +1 -1
  90. package/dist/esm/printing/webusb.d.ts +37 -7
  91. package/dist/esm/printing/webusb.js +74 -17
  92. package/dist/esm/receipt/epos.d.ts +18 -0
  93. package/dist/esm/receipt/epos.js +76 -6
  94. package/dist/esm/receipt/index.d.ts +1 -1
  95. package/dist/esm/receipt/index.js +1 -1
  96. package/dist/esm/register/index.d.ts +1 -1
  97. package/dist/esm/register/index.js +1 -1
  98. package/dist/esm/register/pairing.d.ts +59 -0
  99. package/dist/esm/register/pairing.js +50 -2
  100. package/fixtures/hobex-hps-codes.json +67 -0
  101. package/fixtures/oberflaeche.json +2 -1
  102. package/package.json +4 -2
@@ -2,35 +2,46 @@
2
2
  /**
3
3
  * Unterpfad `@kreiseck/kasseneck-api/payments` — die Zahlungswege, die ein
4
4
  * Browser oder ein Node-Prozess wirklich gehen kann: **Stripe-Zahlungslinks**
5
- * (Fernzahlung per Link/QR-Code) und die **Hobex-Cloud-API** (Kartenzahlung
6
- * ueber ein bei Hobex registriertes Terminal, gesteuert ueber das Netz).
5
+ * (Fernzahlung per Link/QR-Code), die **Hobex-Cloud-API** (Kartenzahlung
6
+ * ueber ein bei Hobex registriertes Terminal, gesteuert ueber das Netz) und
7
+ * **Hobex HPS ueber Kasseneck Connect** (`./hobex-hps.js`) — ein physisches
8
+ * Terminal im Kassen-Netz, angesprochen ueber den lokalen Geraete-Agenten.
7
9
  *
8
10
  * **Was hier bewusst fehlt — und warum es auch nicht nachgeruestet wird:**
9
11
  *
10
- * - **Hobex HPS** spricht **lokal ueber TCP** mit einem angeschlossenen
11
- * Terminal (roher Socket auf eine Geraete-IP im selben Netz).
12
12
  * - **myPOS** und **SumUp** sind **Android-SDKs**; sie laufen als
13
13
  * Bibliothek in einer Android-App und reden ueber Bluetooth bzw. das
14
- * Hersteller-Geraet mit dem Terminal.
14
+ * Hersteller-Geraet mit dem Terminal. Ein Browser hat keine
15
+ * Android-Laufzeit — das ist keine Luecke in diesem Paket und auch nichts,
16
+ * was ein Buendler, ein Polyfill oder WebAssembly aufloest.
15
17
  *
16
- * Ein Browser hat weder rohe TCP-Sockets noch eine Android-Laufzeit. Das ist
17
- * keine Luecke in diesem Paket und auch nichts, was ein anderer Buendler,
18
- * ein Polyfill oder eine WebAssembly-Schicht aufloest es ist eine Grenze der
19
- * Umgebung. Diese drei Wege gibt es im Flutter-Paket `kasseneck_api`, und dort
20
- * bleiben sie.
18
+ * **Frueherer Stand, ueberholt:** hier stand einmal, Hobex HPS sei mangels
19
+ * roher TCP-Sockets im Browser unerreichbar. Das galt fuer den DIREKTEN
20
+ * Terminal-Kontakt (Zwilling: `HpsClient` in `kasseneck_api`) und gilt dafuer
21
+ * weiterhin aber **Kasseneck Connect** ist ein lokaler Geraete-Agent, der
22
+ * ueber gewoehnliches HTTP erreichbar ist und **fuer** die Kasse mit dem
23
+ * Terminal spricht. Das ist kein Widerspruch zur Umgebungsgrenze, sondern ein
24
+ * zweiter, seit `hobex-hps.js` genutzter Weg um sie herum.
25
+ *
26
+ * Wer Gutschrift oder Storno am HPS-Terminal braucht, braucht weiterhin die
27
+ * Flutter-App: Connect exponiert dafuer (noch) keinen Endpunkt, siehe
28
+ * `hobex-hps/connect-client.ts`.
21
29
  *
22
30
  * **Kassen-Benutzer-Weg (`registerUserAuth`, Browser-Kasse):** **Keiner** der
23
- * vier Zahlungs-Endpunkte setzt `allowRegisterUser`; sie laufen alle ueber
24
- * `checkRequest(req, 'user', …)` und damit nur mit `apiKeyAuth`. Dieses Paket
25
- * bildet das **nicht** nach — wer darf, entscheidet allein das Backend. Der
26
- * Hinweis steht **hier** und gilt fuer beide Dateien dieses Unterpfads.
31
+ * vier Cloud-Zahlungs-Endpunkte (Stripe, Hobex-Cloud) setzt `allowRegisterUser`;
32
+ * sie laufen alle ueber `checkRequest(req, 'user', …)` und damit nur mit
33
+ * `apiKeyAuth`. Dieses Paket bildet das **nicht** nach — wer darf, entscheidet
34
+ * allein das Backend. Der Hinweis steht **hier** und gilt fuer die beiden
35
+ * Cloud-Dateien dieses Unterpfads; `hobex-hps.js` spricht kein Kasseneck-Backend
36
+ * und kennt diese Unterscheidung nicht — dort entscheidet allein der
37
+ * Kopplungstoken von Kasseneck Connect.
27
38
  *
28
39
  * Welche **anderen** Endpunkte den Weg offen haben, steht bewusst nirgends in
29
40
  * diesem Paket: eine abgeschriebene Liste veraltet still, und sie hat hier
30
41
  * nichts zu entscheiden.
31
42
  */
32
43
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.newHobexTransactionId = exports.hobexRefund = exports.hobexPay = exports.stripeCaptureIntent = exports.createStripeLink = exports.StripeLinkMode = void 0;
44
+ exports.TRANSACTION_CANCELED_CODE = exports.TERMINAL_BUSY_HTTP_STATUS = exports.TECHNICAL_ERROR_CODE = exports.PREFLIGHT_CONNECT_CODES = exports.parseHpsTransactionResponse = exports.NO_STATEMENT_CODE = exports.NOT_ABORTABLE_CODE = exports.newHpsTransactionId = exports.MAX_TRANSACTION_ID_LENGTH = exports.mayRetrySafely = exports.isValidHpsTransactionId = exports.isUnknownCode = exports.isTechnicalError = exports.isNotAbortable = exports.isNoStatement = exports.isInProgress = exports.isConclusive = exports.isApproved = exports.INVALID_TRANSACTION_CODE = exports.HpsTransactionIdError = exports.HpsPreflightError = exports.HpsConnectTransportError = exports.HpsConnectTerminalError = exports.HpsConnectException = exports.HpsClarifyTimeoutError = exports.HPS_MEASURED_CODES = exports.createHpsTransactionIdGenerator = exports.createHpsPayments = exports.createHpsConnectClient = exports.CARD_NOT_PRESENT_CODE = exports.APPROVED_CODE = exports.ABORTED_CODE = exports.newHobexTransactionId = exports.hobexRefund = exports.hobexPay = exports.stripeCaptureIntent = exports.createStripeLink = exports.StripeLinkMode = void 0;
34
45
  var index_js_1 = require("../enums/index.js");
35
46
  Object.defineProperty(exports, "StripeLinkMode", { enumerable: true, get: function () { return index_js_1.StripeLinkMode; } });
36
47
  var stripe_js_1 = require("./stripe.js");
@@ -40,3 +51,36 @@ var hobex_js_1 = require("./hobex.js");
40
51
  Object.defineProperty(exports, "hobexPay", { enumerable: true, get: function () { return hobex_js_1.hobexPay; } });
41
52
  Object.defineProperty(exports, "hobexRefund", { enumerable: true, get: function () { return hobex_js_1.hobexRefund; } });
42
53
  Object.defineProperty(exports, "newHobexTransactionId", { enumerable: true, get: function () { return hobex_js_1.newHobexTransactionId; } });
54
+ var index_js_2 = require("./hobex-hps/index.js");
55
+ Object.defineProperty(exports, "ABORTED_CODE", { enumerable: true, get: function () { return index_js_2.ABORTED_CODE; } });
56
+ Object.defineProperty(exports, "APPROVED_CODE", { enumerable: true, get: function () { return index_js_2.APPROVED_CODE; } });
57
+ Object.defineProperty(exports, "CARD_NOT_PRESENT_CODE", { enumerable: true, get: function () { return index_js_2.CARD_NOT_PRESENT_CODE; } });
58
+ Object.defineProperty(exports, "createHpsConnectClient", { enumerable: true, get: function () { return index_js_2.createHpsConnectClient; } });
59
+ Object.defineProperty(exports, "createHpsPayments", { enumerable: true, get: function () { return index_js_2.createHpsPayments; } });
60
+ Object.defineProperty(exports, "createHpsTransactionIdGenerator", { enumerable: true, get: function () { return index_js_2.createHpsTransactionIdGenerator; } });
61
+ Object.defineProperty(exports, "HPS_MEASURED_CODES", { enumerable: true, get: function () { return index_js_2.HPS_MEASURED_CODES; } });
62
+ Object.defineProperty(exports, "HpsClarifyTimeoutError", { enumerable: true, get: function () { return index_js_2.HpsClarifyTimeoutError; } });
63
+ Object.defineProperty(exports, "HpsConnectException", { enumerable: true, get: function () { return index_js_2.HpsConnectException; } });
64
+ Object.defineProperty(exports, "HpsConnectTerminalError", { enumerable: true, get: function () { return index_js_2.HpsConnectTerminalError; } });
65
+ Object.defineProperty(exports, "HpsConnectTransportError", { enumerable: true, get: function () { return index_js_2.HpsConnectTransportError; } });
66
+ Object.defineProperty(exports, "HpsPreflightError", { enumerable: true, get: function () { return index_js_2.HpsPreflightError; } });
67
+ Object.defineProperty(exports, "HpsTransactionIdError", { enumerable: true, get: function () { return index_js_2.HpsTransactionIdError; } });
68
+ Object.defineProperty(exports, "INVALID_TRANSACTION_CODE", { enumerable: true, get: function () { return index_js_2.INVALID_TRANSACTION_CODE; } });
69
+ Object.defineProperty(exports, "isApproved", { enumerable: true, get: function () { return index_js_2.isApproved; } });
70
+ Object.defineProperty(exports, "isConclusive", { enumerable: true, get: function () { return index_js_2.isConclusive; } });
71
+ Object.defineProperty(exports, "isInProgress", { enumerable: true, get: function () { return index_js_2.isInProgress; } });
72
+ Object.defineProperty(exports, "isNoStatement", { enumerable: true, get: function () { return index_js_2.isNoStatement; } });
73
+ Object.defineProperty(exports, "isNotAbortable", { enumerable: true, get: function () { return index_js_2.isNotAbortable; } });
74
+ Object.defineProperty(exports, "isTechnicalError", { enumerable: true, get: function () { return index_js_2.isTechnicalError; } });
75
+ Object.defineProperty(exports, "isUnknownCode", { enumerable: true, get: function () { return index_js_2.isUnknownCode; } });
76
+ Object.defineProperty(exports, "isValidHpsTransactionId", { enumerable: true, get: function () { return index_js_2.isValidHpsTransactionId; } });
77
+ Object.defineProperty(exports, "mayRetrySafely", { enumerable: true, get: function () { return index_js_2.mayRetrySafely; } });
78
+ Object.defineProperty(exports, "MAX_TRANSACTION_ID_LENGTH", { enumerable: true, get: function () { return index_js_2.MAX_TRANSACTION_ID_LENGTH; } });
79
+ Object.defineProperty(exports, "newHpsTransactionId", { enumerable: true, get: function () { return index_js_2.newHpsTransactionId; } });
80
+ Object.defineProperty(exports, "NOT_ABORTABLE_CODE", { enumerable: true, get: function () { return index_js_2.NOT_ABORTABLE_CODE; } });
81
+ Object.defineProperty(exports, "NO_STATEMENT_CODE", { enumerable: true, get: function () { return index_js_2.NO_STATEMENT_CODE; } });
82
+ Object.defineProperty(exports, "parseHpsTransactionResponse", { enumerable: true, get: function () { return index_js_2.parseHpsTransactionResponse; } });
83
+ Object.defineProperty(exports, "PREFLIGHT_CONNECT_CODES", { enumerable: true, get: function () { return index_js_2.PREFLIGHT_CONNECT_CODES; } });
84
+ Object.defineProperty(exports, "TECHNICAL_ERROR_CODE", { enumerable: true, get: function () { return index_js_2.TECHNICAL_ERROR_CODE; } });
85
+ Object.defineProperty(exports, "TERMINAL_BUSY_HTTP_STATUS", { enumerable: true, get: function () { return index_js_2.TERMINAL_BUSY_HTTP_STATUS; } });
86
+ Object.defineProperty(exports, "TRANSACTION_CANCELED_CODE", { enumerable: true, get: function () { return index_js_2.TRANSACTION_CANCELED_CODE; } });
@@ -1,3 +1,3 @@
1
1
  export { type PosPaperSize, type PosAlign, type PosFont, type PosCutMode, type PosCodeTable, type PosTextSize, type QrSize, type QrCorrection, type PosStyles, type PosColumn, type EscPosOptions, type EscPosTextOptions, type EscPosHrOptions, type EscPosQrOptions, type EscPosDocument, createEscPosDocument, escPosBytes, escPosReset, escPosSetGlobalCodeTable, escPosSetGlobalFont, escPosSetStyles, escPosText, escPosEmptyLines, escPosFeed, escPosCut, escPosHr, escPosRow, escPosQrCode, encodeEscPosText, qrCodeBytes, escPosMaxCharsPerLine, escPosWortzeilen, wortzeilenText, } from './escpos.js';
2
2
  export { escPosPrintableText } from './printable.js';
3
- export { type UsbEndpointLike, type UsbAlternateLike, type UsbInterfaceLike, type UsbConfigurationLike, type UsbTransferOutResultLike, type UsbWriterLike, type UsbIdentityLike, type UsbDeviceLike, type UsbPrinterEndpoint, type UsbPrinterConnection, USB_VENDOR_EPSON, USB_CLASS_PRINTER, usbDeviceKey, usbFindPrinterEndpoint, usbWriteAll, usbConnectPrinter, usbPrint, usbDisconnect, } from './webusb.js';
3
+ export { type UsbEndpointLike, type UsbAlternateLike, type UsbInterfaceLike, type UsbConfigurationLike, type UsbTransferOutResultLike, type UsbWriterLike, type UsbIdentityLike, type UsbDeviceLike, type UsbPrinterEndpoint, type UsbPrinterConnection, USB_VENDOR_EPSON, USB_CLASS_PRINTER, UsbTimeoutError, usbDeviceKey, usbFindPrinterEndpoint, usbWriteAll, usbConnectPrinter, usbPrint, usbDisconnect, } from './webusb.js';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.usbDisconnect = exports.usbPrint = exports.usbConnectPrinter = exports.usbWriteAll = exports.usbFindPrinterEndpoint = exports.usbDeviceKey = exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = exports.escPosPrintableText = exports.wortzeilenText = exports.escPosWortzeilen = exports.escPosMaxCharsPerLine = exports.qrCodeBytes = exports.encodeEscPosText = exports.escPosQrCode = exports.escPosRow = exports.escPosHr = exports.escPosCut = exports.escPosFeed = exports.escPosEmptyLines = exports.escPosText = exports.escPosSetStyles = exports.escPosSetGlobalFont = exports.escPosSetGlobalCodeTable = exports.escPosReset = exports.escPosBytes = exports.createEscPosDocument = void 0;
3
+ exports.usbDisconnect = exports.usbPrint = exports.usbConnectPrinter = exports.usbWriteAll = exports.usbFindPrinterEndpoint = exports.usbDeviceKey = exports.UsbTimeoutError = exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = exports.escPosPrintableText = exports.wortzeilenText = exports.escPosWortzeilen = exports.escPosMaxCharsPerLine = exports.qrCodeBytes = exports.encodeEscPosText = exports.escPosQrCode = exports.escPosRow = exports.escPosHr = exports.escPosCut = exports.escPosFeed = exports.escPosEmptyLines = exports.escPosText = exports.escPosSetStyles = exports.escPosSetGlobalFont = exports.escPosSetGlobalCodeTable = exports.escPosReset = exports.escPosBytes = exports.createEscPosDocument = void 0;
4
4
  var escpos_js_1 = require("./escpos.js");
5
5
  Object.defineProperty(exports, "createEscPosDocument", { enumerable: true, get: function () { return escpos_js_1.createEscPosDocument; } });
6
6
  Object.defineProperty(exports, "escPosBytes", { enumerable: true, get: function () { return escpos_js_1.escPosBytes; } });
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "escPosPrintableText", { enumerable: true, get: f
25
25
  var webusb_js_1 = require("./webusb.js");
26
26
  Object.defineProperty(exports, "USB_VENDOR_EPSON", { enumerable: true, get: function () { return webusb_js_1.USB_VENDOR_EPSON; } });
27
27
  Object.defineProperty(exports, "USB_CLASS_PRINTER", { enumerable: true, get: function () { return webusb_js_1.USB_CLASS_PRINTER; } });
28
+ Object.defineProperty(exports, "UsbTimeoutError", { enumerable: true, get: function () { return webusb_js_1.UsbTimeoutError; } });
28
29
  Object.defineProperty(exports, "usbDeviceKey", { enumerable: true, get: function () { return webusb_js_1.usbDeviceKey; } });
29
30
  Object.defineProperty(exports, "usbFindPrinterEndpoint", { enumerable: true, get: function () { return webusb_js_1.usbFindPrinterEndpoint; } });
30
31
  Object.defineProperty(exports, "usbWriteAll", { enumerable: true, get: function () { return webusb_js_1.usbWriteAll; } });
@@ -75,15 +75,45 @@ export declare function usbDeviceKey(d: UsbIdentityLike): string;
75
75
  export declare function usbFindPrinterEndpoint(d: {
76
76
  configuration: UsbConfigurationLike | null;
77
77
  }): UsbPrinterEndpoint | null;
78
- /** Bytes blockweise an den OUT-Endpunkt; liefert die geschriebene Gesamtzahl, wirft bei Fehlstatus. */
79
- export declare function usbWriteAll(dev: UsbWriterLike, endpointNumber: number, bytes: Uint8Array, blockSize?: number): Promise<number>;
78
+ /**
79
+ * Ein USB-Schritt kam nicht innerhalb der Frist zurueck. Anders als bei einem
80
+ * HTTP-Aufruf (siehe `receipt/epos.ts`, `EposConnectionError`) kennt WebUSB
81
+ * fuer diese Methoden kein Abbruchsignal -- der zugrunde liegende Transfer
82
+ * kann am Geraet WEITERLAUFEN, auch nachdem dieser Fehler geworfen wurde. Was
83
+ * hier begrenzt wird, ist NUR das Warten dieses Aufrufers, nicht der Transfer
84
+ * selbst. Dieselbe ehrliche Einschraenkung wie beim Dart-Zwilling
85
+ * `HpsPayments` (`_abortBudget`-Kommentar): ein weicher Zeitablauf ist besser
86
+ * als gar keiner, aber kein echtes Abbrechen.
87
+ */
88
+ export declare class UsbTimeoutError extends Error {
89
+ readonly name = "UsbTimeoutError";
90
+ readonly schritt: string;
91
+ readonly timeoutMs: number;
92
+ constructor(schritt: string, timeoutMs: number);
93
+ }
94
+ /**
95
+ * Bytes blockweise an den OUT-Endpunkt; liefert die geschriebene Gesamtzahl,
96
+ * wirft bei Fehlstatus. [timeoutMs] gilt JE Block, nicht fuer den gesamten
97
+ * Druckauftrag -- ein grosser Beleg darf laenger brauchen, ein EINZELNER
98
+ * haengender Block soll trotzdem auffallen, statt den ganzen Aufruf
99
+ * unbegrenzt festzuhalten (genau das Muster, das im Flutter-Paket einen
100
+ * Verkauf angehalten hat).
101
+ */
102
+ export declare function usbWriteAll(dev: UsbWriterLike, endpointNumber: number, bytes: Uint8Array, blockSize?: number, timeoutMs?: number): Promise<number>;
80
103
  /**
81
104
  * Geraet oeffnen, Konfiguration waehlen, Druckerschnittstelle belegen. Wirft
82
105
  * verstaendlich, wenn ein Treiber das Geraet haelt oder kein Drucker-Endpunkt
83
- * da ist -- und schliesst das Geraet dann wieder.
106
+ * da ist -- und schliesst das Geraet dann wieder. Jeder Schritt steht unter
107
+ * [timeoutMs] (siehe [UsbTimeoutError]).
84
108
  */
85
- export declare function usbConnectPrinter(device: UsbDeviceLike): Promise<UsbPrinterConnection>;
109
+ export declare function usbConnectPrinter(device: UsbDeviceLike, timeoutMs?: number): Promise<UsbPrinterConnection>;
86
110
  /** Bytes an eine bestehende Verbindung. */
87
- export declare function usbPrint(c: UsbPrinterConnection, bytes: Uint8Array): Promise<number>;
88
- /** Schnittstelle freigeben und schliessen; Fehler dabei sind egal (Geraet ist ohnehin weg). */
89
- export declare function usbDisconnect(c: UsbPrinterConnection): Promise<void>;
111
+ export declare function usbPrint(c: UsbPrinterConnection, bytes: Uint8Array, timeoutMs?: number): Promise<number>;
112
+ /**
113
+ * Schnittstelle freigeben und schliessen; Fehler dabei sind egal (Geraet ist
114
+ * ohnehin weg) -- ABER ein haengender Aufruf ist etwas anderes als ein Fehler:
115
+ * ein `catch` faengt nur eine ABLEHNUNG ab, nicht ein Versprechen, das nie
116
+ * aufloest. Ohne die Frist haette ein steckengebliebenes `releaseInterface`
117
+ * `usbDisconnect` selbst unbegrenzt haengen lassen, trotz des `try/catch`.
118
+ */
119
+ export declare function usbDisconnect(c: UsbPrinterConnection, timeoutMs?: number): Promise<void>;
@@ -10,7 +10,7 @@
10
10
  * es ohne Browser testbar bleibt und in jeder App gleich laeuft.
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = void 0;
13
+ exports.UsbTimeoutError = exports.USB_CLASS_PRINTER = exports.USB_VENDOR_EPSON = void 0;
14
14
  exports.usbDeviceKey = usbDeviceKey;
15
15
  exports.usbFindPrinterEndpoint = usbFindPrinterEndpoint;
16
16
  exports.usbWriteAll = usbWriteAll;
@@ -44,15 +44,58 @@ function usbFindPrinterEndpoint(d) {
44
44
  kandidaten.sort((a, b) => a.rang - b.rang);
45
45
  return kandidaten[0]?.e ?? null;
46
46
  }
47
- /** Bytes blockweise an den OUT-Endpunkt; liefert die geschriebene Gesamtzahl, wirft bei Fehlstatus. */
48
- async function usbWriteAll(dev, endpointNumber, bytes, blockSize = 16384) {
47
+ /**
48
+ * Ein USB-Schritt kam nicht innerhalb der Frist zurueck. Anders als bei einem
49
+ * HTTP-Aufruf (siehe `receipt/epos.ts`, `EposConnectionError`) kennt WebUSB
50
+ * fuer diese Methoden kein Abbruchsignal -- der zugrunde liegende Transfer
51
+ * kann am Geraet WEITERLAUFEN, auch nachdem dieser Fehler geworfen wurde. Was
52
+ * hier begrenzt wird, ist NUR das Warten dieses Aufrufers, nicht der Transfer
53
+ * selbst. Dieselbe ehrliche Einschraenkung wie beim Dart-Zwilling
54
+ * `HpsPayments` (`_abortBudget`-Kommentar): ein weicher Zeitablauf ist besser
55
+ * als gar keiner, aber kein echtes Abbrechen.
56
+ */
57
+ class UsbTimeoutError extends Error {
58
+ name = 'UsbTimeoutError';
59
+ schritt;
60
+ timeoutMs;
61
+ constructor(schritt, timeoutMs) {
62
+ super(`USB-Drucker antwortet nicht (${schritt}, Zeitlimit ${timeoutMs} ms überschritten) — Kabel/Gerät prüfen.`);
63
+ this.schritt = schritt;
64
+ this.timeoutMs = timeoutMs;
65
+ }
66
+ }
67
+ exports.UsbTimeoutError = UsbTimeoutError;
68
+ /** Vorgabe-Zeitlimit je USB-Schritt. Ein einzelner Block/Schritt braucht Millisekunden; alles darueber ist ein haengendes Geraet. */
69
+ const USB_ZEITLIMIT_VORGABE_MS = 15000;
70
+ /** Begrenzt das WARTEN auf [promise] -- siehe [UsbTimeoutError] fuer die Einschraenkung. */
71
+ function mitZeitlimit(promise, ms, schritt) {
72
+ return new Promise((resolve, reject) => {
73
+ const timer = setTimeout(() => reject(new UsbTimeoutError(schritt, ms)), ms);
74
+ promise.then((v) => {
75
+ clearTimeout(timer);
76
+ resolve(v);
77
+ }, (e) => {
78
+ clearTimeout(timer);
79
+ reject(e);
80
+ });
81
+ });
82
+ }
83
+ /**
84
+ * Bytes blockweise an den OUT-Endpunkt; liefert die geschriebene Gesamtzahl,
85
+ * wirft bei Fehlstatus. [timeoutMs] gilt JE Block, nicht fuer den gesamten
86
+ * Druckauftrag -- ein grosser Beleg darf laenger brauchen, ein EINZELNER
87
+ * haengender Block soll trotzdem auffallen, statt den ganzen Aufruf
88
+ * unbegrenzt festzuhalten (genau das Muster, das im Flutter-Paket einen
89
+ * Verkauf angehalten hat).
90
+ */
91
+ async function usbWriteAll(dev, endpointNumber, bytes, blockSize = 16384, timeoutMs = USB_ZEITLIMIT_VORGABE_MS) {
49
92
  const groesse = Math.max(1, Math.floor(blockSize));
50
93
  let n = 0;
51
94
  for (let von = 0; von < bytes.length; von += groesse) {
52
95
  // eigener ArrayBuffer je Block (BufferSource verlangt kein SharedArrayBuffer)
53
96
  const block = new Uint8Array(Math.min(groesse, bytes.length - von));
54
97
  block.set(bytes.subarray(von, von + block.length));
55
- const r = await dev.transferOut(endpointNumber, block);
98
+ const r = await mitZeitlimit(dev.transferOut(endpointNumber, block), timeoutMs, 'transferOut');
56
99
  if (r.status !== 'ok')
57
100
  throw new Error(`USB-Übertragung: ${r.status} nach ${n} Byte`);
58
101
  n += r.bytesWritten;
@@ -62,49 +105,64 @@ async function usbWriteAll(dev, endpointNumber, bytes, blockSize = 16384) {
62
105
  /**
63
106
  * Geraet oeffnen, Konfiguration waehlen, Druckerschnittstelle belegen. Wirft
64
107
  * verstaendlich, wenn ein Treiber das Geraet haelt oder kein Drucker-Endpunkt
65
- * da ist -- und schliesst das Geraet dann wieder.
108
+ * da ist -- und schliesst das Geraet dann wieder. Jeder Schritt steht unter
109
+ * [timeoutMs] (siehe [UsbTimeoutError]).
66
110
  */
67
- async function usbConnectPrinter(device) {
111
+ async function usbConnectPrinter(device, timeoutMs = USB_ZEITLIMIT_VORGABE_MS) {
68
112
  if (!device.opened)
69
- await device.open();
113
+ await mitZeitlimit(device.open(), timeoutMs, 'open');
70
114
  try {
71
115
  if (!device.configuration)
72
- await device.selectConfiguration(1);
116
+ await mitZeitlimit(device.selectConfiguration(1), timeoutMs, 'selectConfiguration');
73
117
  const ep = usbFindPrinterEndpoint(device);
74
118
  if (!ep)
75
119
  throw new Error('Kein Drucker-Endpunkt am USB-Gerät gefunden — ist das ein Bondrucker?');
76
120
  try {
77
- await device.claimInterface(ep.interfaceNumber);
121
+ await mitZeitlimit(device.claimInterface(ep.interfaceNumber), timeoutMs, 'claimInterface');
78
122
  }
79
123
  catch (e) {
124
+ // Ein Zeitablauf ist etwas anderes als ein abgelehnter Claim: Ersterer
125
+ // sagt "das Geraet antwortet gar nicht", Letzterer "ein Treiber haelt
126
+ // es". Beide unter derselben Meldung zu verstecken, waere dieselbe
127
+ // Verwechslung, die an anderer Stelle in diesem Vorhaben schon einmal
128
+ // Kartendaten falsch eingeordnet hat -- hier nur mit einem Drucker
129
+ // statt eines Terminals.
130
+ if (e instanceof UsbTimeoutError)
131
+ throw e;
80
132
  const grund = e instanceof Error && e.message ? ` (${e.message})` : '';
81
133
  throw new Error(`USB-Schnittstelle belegt${grund} — ein Treiber hält den Drucker. Windows: Epson-Treiber entfernen oder mit Zadig auf WinUSB umstellen.`);
82
134
  }
83
135
  if (ep.alternateSetting !== 0)
84
- await device.selectAlternateInterface(ep.interfaceNumber, ep.alternateSetting);
136
+ await mitZeitlimit(device.selectAlternateInterface(ep.interfaceNumber, ep.alternateSetting), timeoutMs, 'selectAlternateInterface');
85
137
  const name = [device.manufacturerName, device.productName].filter((t) => !!t).join(' ') || 'USB-Drucker';
86
138
  return { device, name, interfaceNumber: ep.interfaceNumber, endpointNumber: ep.endpointNumber, key: usbDeviceKey(device) };
87
139
  }
88
140
  catch (e) {
89
141
  try {
90
- await device.close();
142
+ await mitZeitlimit(device.close(), timeoutMs, 'close');
91
143
  }
92
- catch { /* schon zu */ }
144
+ catch { /* schon zu, oder haengt ebenfalls -- egal, wir werfen ohnehin schon */ }
93
145
  throw e;
94
146
  }
95
147
  }
96
148
  /** Bytes an eine bestehende Verbindung. */
97
- function usbPrint(c, bytes) {
98
- return usbWriteAll(c.device, c.endpointNumber, bytes);
149
+ function usbPrint(c, bytes, timeoutMs = USB_ZEITLIMIT_VORGABE_MS) {
150
+ return usbWriteAll(c.device, c.endpointNumber, bytes, undefined, timeoutMs);
99
151
  }
100
- /** Schnittstelle freigeben und schliessen; Fehler dabei sind egal (Geraet ist ohnehin weg). */
101
- async function usbDisconnect(c) {
152
+ /**
153
+ * Schnittstelle freigeben und schliessen; Fehler dabei sind egal (Geraet ist
154
+ * ohnehin weg) -- ABER ein haengender Aufruf ist etwas anderes als ein Fehler:
155
+ * ein `catch` faengt nur eine ABLEHNUNG ab, nicht ein Versprechen, das nie
156
+ * aufloest. Ohne die Frist haette ein steckengebliebenes `releaseInterface`
157
+ * `usbDisconnect` selbst unbegrenzt haengen lassen, trotz des `try/catch`.
158
+ */
159
+ async function usbDisconnect(c, timeoutMs = USB_ZEITLIMIT_VORGABE_MS) {
102
160
  try {
103
- await c.device.releaseInterface(c.interfaceNumber);
161
+ await mitZeitlimit(c.device.releaseInterface(c.interfaceNumber), timeoutMs, 'releaseInterface');
104
162
  }
105
163
  catch { /* egal */ }
106
164
  try {
107
- await c.device.close();
165
+ await mitZeitlimit(c.device.close(), timeoutMs, 'close');
108
166
  }
109
167
  catch { /* egal */ }
110
168
  }
@@ -47,6 +47,24 @@ export interface EposResponse {
47
47
  export declare function eposServiceUrl(ip: string, devid?: string, timeoutMs?: number): string;
48
48
  export declare function eposSoapEnvelope(innerXml: string): string;
49
49
  export declare function eposParseResponse(text: string): EposResponse;
50
+ /**
51
+ * Ob ein Aufruf an [eposDirectSend] an einem ZEITABLAUF scheiterte oder an
52
+ * einer sonst abgelehnten/nie zustande gekommenen Verbindung -- ein Aufrufer
53
+ * muss das unterscheiden koennen. Ein Zeitablauf heisst "der Drucker koennte
54
+ * noch antworten, spaeter nochmal versuchen"; eine Ablehnung heisst "unter
55
+ * dieser Adresse ist niemand" (falsche IP, Kabel raus, Zertifikat nicht
56
+ * akzeptiert). Vor dieser Klasse trug die eine Fehlermeldung fuer beide
57
+ * Faelle keine maschinenlesbare Unterscheidung -- ein Aufrufer haette sie nur
58
+ * am Text erraten koennen, und genau diese Art von Kopplung an einen Text hat
59
+ * sich an anderer Stelle in diesem Vorhaben schon als brueckig erwiesen.
60
+ */
61
+ export declare class EposConnectionError extends Error {
62
+ readonly name = "EposConnectionError";
63
+ readonly ip: string;
64
+ /** `true`, wenn das Zeitlimit ablief, BEVOR eine Antwort da war. */
65
+ readonly timedOut: boolean;
66
+ constructor(ip: string, timedOut: boolean);
67
+ }
50
68
  /** Beleg direkt drucken; wirft bei Netz-/Zertifikatsproblemen, sonst die Drucker-Antwort. */
51
69
  export declare function eposDirectPrint(layout: ReceiptLayout, o: EposDirectOptions, fetchFn?: typeof fetch): Promise<EposResponse>;
52
70
  /** Verbindungstest: leeres Dokument, druckt nichts, liefert den Druckerstatus. */
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EposConnectionError = void 0;
3
4
  exports.eposXmlEscape = eposXmlEscape;
4
5
  exports.eposPrintXml = eposPrintXml;
5
6
  exports.eposServiceUrl = eposServiceUrl;
@@ -70,19 +71,90 @@ function eposParseResponse(text) {
70
71
  const attr = (n) => new RegExp(`\\b${n}="([^"]*)"`).exec(m[1] ?? '')?.[1] ?? '';
71
72
  return { success: attr('success') === 'true', code: attr('code'), status: attr('status') };
72
73
  }
74
+ /**
75
+ * Ob ein Aufruf an [eposDirectSend] an einem ZEITABLAUF scheiterte oder an
76
+ * einer sonst abgelehnten/nie zustande gekommenen Verbindung -- ein Aufrufer
77
+ * muss das unterscheiden koennen. Ein Zeitablauf heisst "der Drucker koennte
78
+ * noch antworten, spaeter nochmal versuchen"; eine Ablehnung heisst "unter
79
+ * dieser Adresse ist niemand" (falsche IP, Kabel raus, Zertifikat nicht
80
+ * akzeptiert). Vor dieser Klasse trug die eine Fehlermeldung fuer beide
81
+ * Faelle keine maschinenlesbare Unterscheidung -- ein Aufrufer haette sie nur
82
+ * am Text erraten koennen, und genau diese Art von Kopplung an einen Text hat
83
+ * sich an anderer Stelle in diesem Vorhaben schon als brueckig erwiesen.
84
+ */
85
+ class EposConnectionError extends Error {
86
+ name = 'EposConnectionError';
87
+ ip;
88
+ /** `true`, wenn das Zeitlimit ablief, BEVOR eine Antwort da war. */
89
+ timedOut;
90
+ constructor(ip, timedOut) {
91
+ const grund = timedOut ? 'antwortet nicht (Zeitlimit überschritten)' : 'nicht erreichbar';
92
+ super(`Drucker ${grund}. Einmal https://${ip.trim()} im Browser öffnen und das Zertifikat akzeptieren, ` +
93
+ 'Zugriff aufs lokale Netz erlauben, ePOS-Print am Drucker auf Enable.');
94
+ this.ip = ip;
95
+ this.timedOut = timedOut;
96
+ }
97
+ }
98
+ exports.EposConnectionError = EposConnectionError;
99
+ /** Lehnt ab, sobald [signal] abbricht -- die Naht fuer die Frist in [eposDirectSend]. */
100
+ function alsAbbruchAbgelehnt(signal) {
101
+ return new Promise((_erfuellen, ablehnen) => {
102
+ if (signal.aborted) {
103
+ ablehnen(new Error('abgebrochen'));
104
+ return;
105
+ }
106
+ signal.addEventListener('abort', () => ablehnen(new Error('abgebrochen')), { once: true });
107
+ });
108
+ }
73
109
  async function eposDirectSend(innerXml, o, fetchFn) {
74
- const url = eposServiceUrl(o.ip, o.devid ?? EPOS_DEVID_VORGABE, o.timeoutMs ?? 10000);
110
+ const zeitlimitMs = o.timeoutMs ?? 10000;
111
+ const url = eposServiceUrl(o.ip, o.devid ?? EPOS_DEVID_VORGABE, zeitlimitMs);
112
+ // `zeitlimitMs` geht zweifach ein -- als `timeout=`-Parameter in der URL
113
+ // (ein Hinweis FUER DEN DRUCKER, wie lange ER intern auf den Kartenfluss/
114
+ // Druckvorgang wartet) UND als AbortController-Frist HIER (die Grenze fuer
115
+ // DIESEN Aufruf). Das ist keine Dopplung, sondern zwei verschiedene Dinge,
116
+ // die zufaellig denselben Wert teilen: ohne die zweite Haelfte begrenzt
117
+ // NICHTS den `fetch()`-Aufruf selbst. Ein Drucker, der die TCP-Verbindung
118
+ // annimmt und nie antwortet (ein reales Fehlerbild bei einem eingebetteten
119
+ // HTTP-Server), liesse den Aufruf dann NIE zurueckkehren und NIE werfen --
120
+ // genau dieses Muster hat im Flutter-Paket einen ganzen Verkauf angehalten:
121
+ // der Beleg stand in der Signaturkette, der Bildschirm zeigte nichts, und
122
+ // ein Neustart mit erneutem Kassieren erzeugte einen zweiten Umsatz.
123
+ const abbruch = new AbortController();
124
+ const wecker = setTimeout(() => abbruch.abort(), zeitlimitMs);
75
125
  let antwort;
126
+ let text;
76
127
  try {
77
- antwort = await fetchFn(url, { method: 'POST', headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: '""' }, body: eposSoapEnvelope(innerXml) });
128
+ try {
129
+ antwort = await Promise.race([
130
+ fetchFn(url, {
131
+ method: 'POST',
132
+ headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: '""' },
133
+ body: eposSoapEnvelope(innerXml),
134
+ signal: abbruch.signal,
135
+ }),
136
+ alsAbbruchAbgelehnt(abbruch.signal),
137
+ ]);
138
+ // Die Frist deckt auch das Auslesen des Rumpfes, nicht nur den
139
+ // Antwortkopf -- ein Drucker, der den Kopf schickt und den Rumpf offen
140
+ // laesst, haelt den Aufruf sonst trotzdem unbegrenzt fest (dasselbe
141
+ // Muster wie `client/transport.ts`).
142
+ text = await Promise.race([antwort.text(), alsAbbruchAbgelehnt(abbruch.signal)]);
143
+ }
144
+ catch {
145
+ // `abbruch.signal.aborted` ist hier zuverlaessig: der EINZIGE Ausloeser
146
+ // fuer den Abbruch in dieser Funktion ist der `wecker` oben -- jeder
147
+ // andere Fehlschlag (Netz weg, Zertifikat abgelehnt, DNS) laesst das
148
+ // Signal unangetastet.
149
+ throw new EposConnectionError(o.ip, abbruch.signal.aborted);
150
+ }
78
151
  }
79
- catch {
80
- throw new Error(`Drucker nicht erreichbar. Einmal https://${o.ip.trim()} im Browser öffnen und das Zertifikat akzeptieren, ` +
81
- 'Zugriff aufs lokale Netz erlauben, ePOS-Print am Drucker auf Enable.');
152
+ finally {
153
+ clearTimeout(wecker);
82
154
  }
83
155
  if (!antwort.ok)
84
156
  throw new Error(`Drucker antwortet mit HTTP ${antwort.status}.`);
85
- return eposParseResponse(await antwort.text());
157
+ return eposParseResponse(text);
86
158
  }
87
159
  /** Beleg direkt drucken; wirft bei Netz-/Zertifikatsproblemen, sonst die Drucker-Antwort. */
88
160
  function eposDirectPrint(layout, o, fetchFn = fetch) {
@@ -1,4 +1,4 @@
1
1
  export { type LayoutAlign, type LayoutColumn, type LayoutTextLine, type LayoutColumnsLine, type LayoutRuleLine, type LayoutSpaceLine, type LayoutQrLine, type LayoutLine, type ReceiptLayout, type BuildReceiptLayoutOptions, buildReceiptLayout, receiptSignatureFailed, receiptSignatureIsTest, receiptIsZero, receiptAmountsAreZero, receiptIsSmallBusinessConsistent, receiptZdaText, type Pruefangaben, AKTUELLES_REGELWERK, type LayoutBannerLine, type LayoutRegelwerk, SMALL_BUSINESS_NOTICE, formatCents, } from './layout.js';
2
2
  export { type EscPosLayoutOptions, escPosLayoutBytes } from './layout-escpos.js';
3
3
  export { type GridLine, type GridLineKind, type ReceiptGrid, type RenderReceiptGridOptions, renderReceiptGrid, gridSpaltenBreiten, gridAlsText, ZEICHEN_JE_PAPIER, } from './grid.js';
4
- export { type EposPrintXmlOptions, type EposDirectOptions, type EposResponse, eposPrintXml, eposXmlEscape, eposServiceUrl, eposSoapEnvelope, eposParseResponse, eposDirectPrint, eposDirectStatus } from './epos.js';
4
+ export { type EposPrintXmlOptions, type EposDirectOptions, type EposResponse, EposConnectionError, eposPrintXml, eposXmlEscape, eposServiceUrl, eposSoapEnvelope, eposParseResponse, eposDirectPrint, eposDirectStatus } from './epos.js';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposXmlEscape = exports.eposPrintXml = exports.ZEICHEN_JE_PAPIER = exports.gridAlsText = exports.gridSpaltenBreiten = exports.renderReceiptGrid = exports.escPosLayoutBytes = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.AKTUELLES_REGELWERK = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
3
+ exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposXmlEscape = exports.eposPrintXml = exports.EposConnectionError = exports.ZEICHEN_JE_PAPIER = exports.gridAlsText = exports.gridSpaltenBreiten = exports.renderReceiptGrid = exports.escPosLayoutBytes = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.AKTUELLES_REGELWERK = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
4
4
  var layout_js_1 = require("./layout.js");
5
5
  Object.defineProperty(exports, "buildReceiptLayout", { enumerable: true, get: function () { return layout_js_1.buildReceiptLayout; } });
6
6
  Object.defineProperty(exports, "receiptSignatureFailed", { enumerable: true, get: function () { return layout_js_1.receiptSignatureFailed; } });
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "gridSpaltenBreiten", { enumerable: true, get: fu
20
20
  Object.defineProperty(exports, "gridAlsText", { enumerable: true, get: function () { return grid_js_1.gridAlsText; } });
21
21
  Object.defineProperty(exports, "ZEICHEN_JE_PAPIER", { enumerable: true, get: function () { return grid_js_1.ZEICHEN_JE_PAPIER; } });
22
22
  var epos_js_1 = require("./epos.js");
23
+ Object.defineProperty(exports, "EposConnectionError", { enumerable: true, get: function () { return epos_js_1.EposConnectionError; } });
23
24
  Object.defineProperty(exports, "eposPrintXml", { enumerable: true, get: function () { return epos_js_1.eposPrintXml; } });
24
25
  Object.defineProperty(exports, "eposXmlEscape", { enumerable: true, get: function () { return epos_js_1.eposXmlEscape; } });
25
26
  Object.defineProperty(exports, "eposServiceUrl", { enumerable: true, get: function () { return epos_js_1.eposServiceUrl; } });
@@ -47,5 +47,5 @@
47
47
  * daraus entstehende ID-Token und `sitzung.sessionId` ergeben zusammen
48
48
  * `registerUserAuth` — ab da laeuft alles Weitere ueber den ueblichen Weg.
49
49
  */
50
- export { type RegisterDeviceConnection, type RegisterDeviceCredentials, type PairRegisterDeviceOptions, type PairedRegisterDevice, type RegisterUserKind, type RegisterUserSummary, type RegisterUserPerms, REGISTER_PERMS, type RegisterScope, type RegisterUser, type RegisterUserSession, type ListRegisterUsersForDeviceOptions, type RegisterUserLoginOptions, type RegisterPinLoginOptions, type RegisterPinPolicy, type RegisterLoginMode, type RegisterDeviceUsers, type RegisterClientInfo, type RegisterGeo, type RegisterGeraeteAngaben, pairRegisterDevice, listRegisterUsersForDevice, unpairRegisterDevice, registerUserLogin, registerPinLogin, } from './pairing.js';
50
+ export { type RegisterDeviceConnection, type RegisterDeviceCredentials, type PairRegisterDeviceOptions, type PairedRegisterDevice, type RegisterUserKind, type RegisterUserSummary, type RegisterUserPerms, REGISTER_PERMS, type RegisterScope, type RegisterUser, type RegisterUserSession, type ListRegisterUsersForDeviceOptions, type RegisterUserLoginOptions, type RegisterPinLoginOptions, type RegisterPinPolicy, type RegisterLoginMode, type RegisterDeviceUsers, type RegisterClientInfo, type RegisterGeo, type RegisterGeraeteAngaben, type RegisterSession, type RegisterSessionsStand, type ListRegisterSessionsForDeviceOptions, pairRegisterDevice, listRegisterUsersForDevice, listRegisterSessionsForDevice, unpairRegisterDevice, registerUserLogin, registerPinLogin, } from './pairing.js';
51
51
  export { renewRegisterSession, endRegisterSession } from './session.js';
@@ -49,11 +49,12 @@
49
49
  * `registerUserAuth` — ab da laeuft alles Weitere ueber den ueblichen Weg.
50
50
  */
51
51
  Object.defineProperty(exports, "__esModule", { value: true });
52
- exports.endRegisterSession = exports.renewRegisterSession = exports.registerPinLogin = exports.registerUserLogin = exports.unpairRegisterDevice = exports.listRegisterUsersForDevice = exports.pairRegisterDevice = exports.REGISTER_PERMS = void 0;
52
+ exports.endRegisterSession = exports.renewRegisterSession = exports.registerPinLogin = exports.registerUserLogin = exports.unpairRegisterDevice = exports.listRegisterSessionsForDevice = exports.listRegisterUsersForDevice = exports.pairRegisterDevice = exports.REGISTER_PERMS = void 0;
53
53
  var pairing_js_1 = require("./pairing.js");
54
54
  Object.defineProperty(exports, "REGISTER_PERMS", { enumerable: true, get: function () { return pairing_js_1.REGISTER_PERMS; } });
55
55
  Object.defineProperty(exports, "pairRegisterDevice", { enumerable: true, get: function () { return pairing_js_1.pairRegisterDevice; } });
56
56
  Object.defineProperty(exports, "listRegisterUsersForDevice", { enumerable: true, get: function () { return pairing_js_1.listRegisterUsersForDevice; } });
57
+ Object.defineProperty(exports, "listRegisterSessionsForDevice", { enumerable: true, get: function () { return pairing_js_1.listRegisterSessionsForDevice; } });
57
58
  Object.defineProperty(exports, "unpairRegisterDevice", { enumerable: true, get: function () { return pairing_js_1.unpairRegisterDevice; } });
58
59
  Object.defineProperty(exports, "registerUserLogin", { enumerable: true, get: function () { return pairing_js_1.registerUserLogin; } });
59
60
  Object.defineProperty(exports, "registerPinLogin", { enumerable: true, get: function () { return pairing_js_1.registerPinLogin; } });
@@ -27,6 +27,14 @@ export interface RegisterClientInfo {
27
27
  w: number;
28
28
  h: number;
29
29
  };
30
+ /**
31
+ * Welcher Build der Anwendung gerade laeuft (frei, z. B. "0.6.46+3120").
32
+ * Bei einer Stoerungsmeldung die entscheidende Angabe: ohne sie laesst sich
33
+ * ein alter Build im Browser-Cache weder belegen noch ausschliessen -- und
34
+ * genau der steckt oft hinter "bei mir geht es aber". Das Backend kuerzt auf
35
+ * 80 Zeichen (register-geraetedaten.js, clientAusParams).
36
+ */
37
+ app?: string;
30
38
  }
31
39
  /** Standort aus der Browser-Ortung (freiwillig); Grundlage der Standortsperre. */
32
40
  export interface RegisterGeo {
@@ -214,6 +222,15 @@ export interface RegisterUserLoginOptions extends RegisterDeviceConnection, Regi
214
222
  * es bei der Abweisung "Kasse wird gerade auf … verwendet".
215
223
  */
216
224
  takeover?: boolean;
225
+ /**
226
+ * Welche Sitzung soll weichen? Kennung aus [listRegisterSessionsForDevice].
227
+ * Ohne Angabe verdraengt das Backend die aelteste -- so wie bisher.
228
+ *
229
+ * Eine Kennung, die nicht mehr laeuft, wird ABGEWIESEN statt still durch die
230
+ * aelteste ersetzt: Wer waehlt, bekommt seine Wahl oder eine Fehlermeldung,
231
+ * nie einen Unbeteiligten.
232
+ */
233
+ takeoverSessionId?: string;
217
234
  }
218
235
  export interface RegisterPinLoginOptions extends RegisterDeviceConnection, RegisterDeviceCredentials, RegisterGeraeteAngaben {
219
236
  /**
@@ -227,6 +244,8 @@ export interface RegisterPinLoginOptions extends RegisterDeviceConnection, Regis
227
244
  cashregisterId: string;
228
245
  /** Wie [RegisterUserLoginOptions.takeover]. */
229
246
  takeover?: boolean;
247
+ /** Wie [RegisterUserLoginOptions.takeoverSessionId]. */
248
+ takeoverSessionId?: string;
230
249
  }
231
250
  /**
232
251
  * Geraet koppeln: der Kopplungs-Code wird gegen den dauerhaften Ausweis dieses
@@ -252,6 +271,46 @@ export declare function pairRegisterDevice(options: PairRegisterDeviceOptions):
252
271
  * Geraet meldet Erfolg. Danach das Geraet lokal vergessen.
253
272
  */
254
273
  export declare function unpairRegisterDevice(options: ListRegisterUsersForDeviceOptions): Promise<void>;
274
+ /** Eine laufende Sitzung an einer Kasse -- Zeile in der Auswahl. */
275
+ export interface RegisterSession {
276
+ id: string;
277
+ deviceId: string | null;
278
+ /** Name des Geraets; „Kasse", wenn keiner gesetzt wurde. */
279
+ deviceLabel: string;
280
+ startedAt: number | null;
281
+ expiresAt: number | null;
282
+ /** Laeuft diese Sitzung auf DIESEM Geraet? */
283
+ selbst: boolean;
284
+ /**
285
+ * Wer angemeldet ist. Fehlt an einem nur-PIN-Geraet: Dort zeigt schon die
286
+ * Benutzerliste keine Namen, und was dort nicht steht, darf hier nicht
287
+ * durch die Hintertuer kommen. `undefined` heisst „wird nicht genannt",
288
+ * nicht „hat keinen Namen".
289
+ */
290
+ userName?: string;
291
+ }
292
+ /** Was eine Kasse gerade haelt -- Lizenzzahl und laufende Sitzungen. */
293
+ export interface RegisterSessionsStand {
294
+ /** Wie viele Sitzungen gleichzeitig laufen duerfen. */
295
+ licenses: number;
296
+ /** Aelteste zuerst: oben steht, was das Backend ohne Wahl verdraengen wuerde. */
297
+ sessions: RegisterSession[];
298
+ }
299
+ export interface ListRegisterSessionsForDeviceOptions extends RegisterDeviceConnection, RegisterDeviceCredentials {
300
+ }
301
+ /**
302
+ * Welche Sitzungen haelt diese Kasse gerade?
303
+ *
304
+ * Fuer den Anmeldebildschirm: Sind alle Lizenzplaetze belegt, muss eine
305
+ * weichen -- und der Kassier soll sehen, WELCHE, statt dass das Backend still
306
+ * die aelteste nimmt. Die Wahl geht dann als
307
+ * [RegisterUserLoginOptions.takeoverSessionId] mit.
308
+ *
309
+ * Ausgewiesen wird sich ueber das Geraete-Geheimnis, wie bei
310
+ * [listRegisterUsersForDevice]: An diesem Punkt gibt es weder Sitzung noch
311
+ * Token. Die Kasse bestimmt das Backend aus dem Geraet, nicht aus dem Aufruf.
312
+ */
313
+ export declare function listRegisterSessionsForDevice(options: ListRegisterSessionsForDeviceOptions): Promise<RegisterSessionsStand>;
255
314
  export declare function listRegisterUsersForDevice(options: ListRegisterUsersForDeviceOptions): Promise<RegisterDeviceUsers>;
256
315
  /**
257
316
  * Kassen-Benutzer per PIN anmelden. **Ohne Anmeldung** — dieser Aufruf