kassza 0.12.0 → 0.14.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 (177) hide show
  1. package/README.en.md +48 -0
  2. package/README.md +427 -32
  3. package/agents/README.md +26 -6
  4. package/agents/api.md +218 -3
  5. package/agents/pitfalls.md +27 -3
  6. package/agents/recipes.md +280 -51
  7. package/agents/skills/kassza/SKILL.md +14 -8
  8. package/agents/skills/migrate-from-szamlazz-js/SKILL.md +39 -0
  9. package/dist/batch/index.cjs +346 -0
  10. package/dist/batch/index.d.cts +91 -0
  11. package/dist/batch/index.d.ts +91 -0
  12. package/dist/batch/index.js +339 -0
  13. package/dist/cli.cjs +643 -0
  14. package/dist/cli.d.cts +1 -0
  15. package/dist/cli.d.ts +1 -0
  16. package/dist/cli.js +643 -0
  17. package/dist/client-CLFvJCVW.cjs +1452 -0
  18. package/dist/{client-CL3fuH6A.js → client-Cvf-hTz_.js} +306 -515
  19. package/dist/client-DeWWQ-RZ.d.ts +341 -0
  20. package/dist/client-SVZu25MB.d.cts +341 -0
  21. package/dist/context-CFNKzStE.d.cts +449 -0
  22. package/dist/context-kb33TgzE.d.ts +449 -0
  23. package/dist/cookie-stores/index.cjs +21 -150
  24. package/dist/cookie-stores/index.d.cts +4 -63
  25. package/dist/cookie-stores/index.d.ts +4 -63
  26. package/dist/cookie-stores/index.js +3 -144
  27. package/dist/create-CflXrPip.js +204 -0
  28. package/dist/create-CvUvLUaT.cjs +257 -0
  29. package/dist/{create-once-D0pwuenl.cjs → create-once-9yxR_Er_.cjs} +291 -33
  30. package/dist/create-once-Bh6fOWkW.d.cts +20 -0
  31. package/dist/{create-once-CqdYmQD8.js → create-once-Ca2gMk1h.js} +250 -34
  32. package/dist/create-once-VKp0tVow.d.ts +20 -0
  33. package/dist/{crypto-B8lERvR1.cjs → crypto-Dpn4FHQ6.cjs} +9 -0
  34. package/dist/{crypto-DK_osBVy.js → crypto-usDg8L2K.js} +4 -1
  35. package/dist/data-link/index.cjs +232 -0
  36. package/dist/data-link/index.d.cts +29 -0
  37. package/dist/data-link/index.d.ts +29 -0
  38. package/dist/data-link/index.js +224 -0
  39. package/dist/delegation/index.cjs +35 -34
  40. package/dist/delegation/index.d.cts +2 -1
  41. package/dist/delegation/index.d.ts +2 -1
  42. package/dist/delegation/index.js +4 -3
  43. package/dist/{errors-DLrb0g64.js → errors-DtN4g5Z9.js} +9 -1
  44. package/dist/{errors-DxeuTslP.cjs → errors-EE96_6D_.cjs} +20 -0
  45. package/dist/get-BdMTseh4.cjs +271 -0
  46. package/dist/get-Byc9T5WO.d.cts +151 -0
  47. package/dist/get-Byc9T5WO.d.ts +151 -0
  48. package/dist/get-CZEShCcj.js +260 -0
  49. package/dist/index-BhUPY_EH.d.cts +109 -0
  50. package/dist/index-BqGgQ4t3.d.ts +109 -0
  51. package/dist/{index-CYAGCdKJ.d.cts → index-C-7yWV7L.d.cts} +24 -1
  52. package/dist/{index-CYAGCdKJ.d.ts → index-C-7yWV7L.d.ts} +24 -1
  53. package/dist/index.cjs +19 -5
  54. package/dist/index.d.cts +11 -19
  55. package/dist/index.d.ts +11 -19
  56. package/dist/index.js +6 -6
  57. package/dist/ipn/index.cjs +26 -5
  58. package/dist/ipn/index.d.cts +12 -1
  59. package/dist/ipn/index.d.ts +12 -1
  60. package/dist/ipn/index.js +26 -6
  61. package/dist/issue-Bin4tKD_.cjs +988 -0
  62. package/dist/issue-DMA1Nbr1.js +905 -0
  63. package/dist/journal/index.cjs +454 -0
  64. package/dist/journal/index.d.cts +18 -0
  65. package/dist/journal/index.d.ts +18 -0
  66. package/dist/journal/index.js +445 -0
  67. package/dist/journal-DvI81Kt7.d.cts +114 -0
  68. package/dist/journal-Y9qrIB8G.d.ts +114 -0
  69. package/dist/mcp/index.cjs +10 -0
  70. package/dist/mcp/index.d.cts +71 -0
  71. package/dist/mcp/index.d.ts +71 -0
  72. package/dist/mcp/index.js +2 -0
  73. package/dist/money/index.cjs +2 -1
  74. package/dist/money/index.d.cts +2 -2
  75. package/dist/money/index.d.ts +2 -2
  76. package/dist/money/index.js +2 -2
  77. package/dist/{money-DAA7OwiO.js → money-Cw457SD6.js} +120 -12
  78. package/dist/{money-DrhGkWHW.cjs → money-K9j0wPit.cjs} +124 -10
  79. package/dist/nav/index.cjs +1046 -0
  80. package/dist/nav/index.d.cts +247 -0
  81. package/dist/nav/index.d.ts +247 -0
  82. package/dist/nav/index.js +1012 -0
  83. package/dist/nav-BNbc8U0R.cjs +203 -0
  84. package/dist/nav-BcCerwWS.js +156 -0
  85. package/dist/node/index.cjs +124 -0
  86. package/dist/node/index.d.cts +35 -0
  87. package/dist/node/index.d.ts +35 -0
  88. package/dist/node/index.js +120 -0
  89. package/dist/observe/index.cjs +311 -0
  90. package/dist/observe/index.d.cts +53 -0
  91. package/dist/observe/index.d.ts +53 -0
  92. package/dist/observe/index.js +303 -0
  93. package/dist/once-BN_3B5OF.cjs +103 -0
  94. package/dist/once-CqqZxsXG.js +74 -0
  95. package/dist/parse-Cr7yQ3_z.js +291 -0
  96. package/dist/parse-DOA2XQ3e.cjs +380 -0
  97. package/dist/payments/barion.cjs +26 -2
  98. package/dist/payments/barion.d.cts +2 -2
  99. package/dist/payments/barion.d.ts +2 -2
  100. package/dist/payments/barion.js +26 -2
  101. package/dist/payments/index.cjs +7 -2
  102. package/dist/payments/index.d.cts +4 -4
  103. package/dist/payments/index.d.ts +4 -4
  104. package/dist/payments/index.js +3 -3
  105. package/dist/payments/paypal.cjs +16 -2
  106. package/dist/payments/paypal.d.cts +2 -2
  107. package/dist/payments/paypal.d.ts +2 -2
  108. package/dist/payments/paypal.js +16 -2
  109. package/dist/payments/revolut.cjs +17 -3
  110. package/dist/payments/revolut.d.cts +2 -2
  111. package/dist/payments/revolut.d.ts +2 -2
  112. package/dist/payments/revolut.js +17 -3
  113. package/dist/payments/simplepay.cjs +37 -5
  114. package/dist/payments/simplepay.d.cts +2 -2
  115. package/dist/payments/simplepay.d.ts +2 -2
  116. package/dist/payments/simplepay.js +37 -5
  117. package/dist/payments/stripe.cjs +20 -3
  118. package/dist/payments/stripe.d.cts +2 -2
  119. package/dist/payments/stripe.d.ts +2 -2
  120. package/dist/payments/stripe.js +20 -3
  121. package/dist/push-BXj0Sf0Z.d.ts +52 -0
  122. package/dist/push-D4nNbCNV.d.cts +52 -0
  123. package/dist/reference-B5TATqb5.js +124 -0
  124. package/dist/reference-BIdYMK0t.cjs +183 -0
  125. package/dist/reports/index.cjs +11 -164
  126. package/dist/reports/index.d.cts +1 -1
  127. package/dist/reports/index.d.ts +1 -1
  128. package/dist/reports/index.js +1 -154
  129. package/dist/request-body-CH6ZGOrq.cjs +34 -0
  130. package/dist/request-body-uZHMRlQr.js +29 -0
  131. package/dist/serialize-B2eFh3D-.js +219 -0
  132. package/dist/serialize-CquIsxA-.cjs +290 -0
  133. package/dist/server-BrJUbXs7.js +1505 -0
  134. package/dist/server-Dw9j8Mnd.cjs +1558 -0
  135. package/dist/session-Ckl5eJhV.d.ts +7 -0
  136. package/dist/{session-CKOuE6Jc.cjs → session-DeM5vjvC.cjs} +69 -13
  137. package/dist/{session-rMKaJcmq.js → session-SaEEXu2N.js} +58 -14
  138. package/dist/session-YbChChx7.d.cts +7 -0
  139. package/dist/storage/fs.cjs +1 -1
  140. package/dist/storage/fs.js +1 -1
  141. package/dist/storage/index.cjs +1 -1
  142. package/dist/storage/index.js +1 -1
  143. package/dist/store-C1rHd9DB.d.cts +19 -0
  144. package/dist/store-C1rHd9DB.d.ts +19 -0
  145. package/dist/stores/index.cjs +24 -0
  146. package/dist/stores/index.d.cts +4 -0
  147. package/dist/stores/index.d.ts +4 -0
  148. package/dist/stores/index.js +3 -0
  149. package/dist/stores-BNrS0dWl.cjs +506 -0
  150. package/dist/stores-DhjGBrl_.js +441 -0
  151. package/dist/testing/index.cjs +1500 -15
  152. package/dist/testing/index.d.cts +198 -3
  153. package/dist/testing/index.d.ts +198 -3
  154. package/dist/testing/index.js +1498 -15
  155. package/dist/{types-COf1LAD-.d.ts → types-B1A8mUIE.d.cts} +14 -2
  156. package/dist/{types-COf1LAD-.d.cts → types-ByAEvGsZ.d.ts} +14 -2
  157. package/dist/{types-k--zHf4l.d.ts → types-D1zDOH_F.d.ts} +1 -1
  158. package/dist/{types-DH8QoNZK.d.cts → types-lnKkQdot.d.cts} +1 -1
  159. package/dist/warnings-B3DXnveC.d.cts +31 -0
  160. package/dist/warnings-B3DXnveC.d.ts +31 -0
  161. package/dist/warnings-DeIw5RFj.cjs +20 -0
  162. package/dist/warnings-DwTl5J-2.js +15 -0
  163. package/dist/{webhook-D4lvtex1.js → webhook-CQVShAfI.js} +47 -26
  164. package/dist/{webhook-C76bV-4R.cjs → webhook-Ckj-_hPD.cjs} +70 -25
  165. package/dist/webhook-CmdhGiH5.d.cts +11 -0
  166. package/dist/webhook-D6lEejob.d.ts +11 -0
  167. package/llms.txt +6 -5
  168. package/package.json +134 -4
  169. package/dist/client-CickRRFr.d.ts +0 -838
  170. package/dist/client-CsmGIFRS.cjs +0 -1637
  171. package/dist/client-DvWZoX_E.d.cts +0 -838
  172. package/dist/issue-BsyYdrIG.cjs +0 -1531
  173. package/dist/issue-C6Fcjvln.js +0 -1274
  174. package/dist/session-Dm_45x8K.d.cts +0 -11
  175. package/dist/session-Dm_45x8K.d.ts +0 -11
  176. package/dist/webhook-CfaDgcL0.d.cts +0 -6
  177. package/dist/webhook-q2OzNwd7.d.ts +0 -6
@@ -0,0 +1,1452 @@
1
+ const require_create_once = require("./create-once-9yxR_Er_.cjs");
2
+ const require_errors = require("./errors-EE96_6D_.cjs");
3
+ const require_binary = require("./binary-B89HM03_.cjs");
4
+ const require_serialize = require("./serialize-CquIsxA-.cjs");
5
+ const require_parse = require("./parse-DOA2XQ3e.cjs");
6
+ const require_session = require("./session-DeM5vjvC.cjs");
7
+ const require_warnings = require("./warnings-DeIw5RFj.cjs");
8
+ const require_issue = require("./issue-Bin4tKD_.cjs");
9
+ const require_vat = require("./vat-g35srbNG.cjs");
10
+ const require_money = require("./money-K9j0wPit.cjs");
11
+ const require_reference = require("./reference-BIdYMK0t.cjs");
12
+ const require_get = require("./get-BdMTseh4.cjs");
13
+ const require_create = require("./create-CvUvLUaT.cjs");
14
+ //#region src/core/attempt-ledger.ts
15
+ const ATTEMPT_LEDGER_TTL_SECONDS = 86400;
16
+ const ATTEMPT_LEDGER_KEY_PREFIX = "szamlazz:attempts:";
17
+ const COUNTED_CATEGORIES = /* @__PURE__ */ new Set([
18
+ "auth",
19
+ "account",
20
+ "validation",
21
+ "maintenance",
22
+ "rate_limit",
23
+ "network",
24
+ "timeout",
25
+ "unexpected_response",
26
+ "unknown"
27
+ ]);
28
+ function countsAsFailedAttempt(error) {
29
+ return COUNTED_CATEGORIES.has(error.category);
30
+ }
31
+ const encoder = new TextEncoder();
32
+ async function attemptLedgerKey(request) {
33
+ const attachments = (request.attachments ?? []).map((attachment) => `${attachment.filename}:${attachment.size}`).join("|");
34
+ const digest = await crypto.subtle.digest("SHA-256", encoder.encode(`${request.action}\n${request.xml}\n${attachments}`));
35
+ const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0"));
36
+ return `${ATTEMPT_LEDGER_KEY_PREFIX}${hex.join("")}`;
37
+ }
38
+ function parseCount(value) {
39
+ if (value === void 0 || value === null) return 0;
40
+ const parsed = Number.parseInt(value, 10);
41
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
42
+ }
43
+ function createLocalCounter() {
44
+ const counts = /* @__PURE__ */ new Map();
45
+ const get = (key) => {
46
+ const entry = counts.get(key);
47
+ if (!entry) return 0;
48
+ if (entry.expiresAt <= Date.now()) {
49
+ counts.delete(key);
50
+ return 0;
51
+ }
52
+ return entry.count;
53
+ };
54
+ return {
55
+ get,
56
+ bump(key) {
57
+ const count = get(key) + 1;
58
+ counts.delete(key);
59
+ counts.set(key, {
60
+ count,
61
+ expiresAt: Date.now() + ATTEMPT_LEDGER_TTL_SECONDS * 1e3
62
+ });
63
+ if (counts.size > 1e3) {
64
+ const oldest = counts.keys().next().value;
65
+ if (oldest !== void 0) counts.delete(oldest);
66
+ }
67
+ },
68
+ clear(key) {
69
+ counts.delete(key);
70
+ }
71
+ };
72
+ }
73
+ function createAttemptLedger(store) {
74
+ const local = createLocalCounter();
75
+ const unpersisted = createLocalCounter();
76
+ return {
77
+ async failures(key) {
78
+ return parseCount(await store.get(key)) + unpersisted.get(key);
79
+ },
80
+ fallbackFailures(key) {
81
+ return local.get(key);
82
+ },
83
+ async recordFailure(key) {
84
+ local.bump(key);
85
+ try {
86
+ if (store.increment) {
87
+ await store.increment(key, ATTEMPT_LEDGER_TTL_SECONDS);
88
+ return;
89
+ }
90
+ const current = parseCount(await store.get(key));
91
+ await store.set(key, String(current + 1), ATTEMPT_LEDGER_TTL_SECONDS);
92
+ } catch (error) {
93
+ unpersisted.bump(key);
94
+ throw error;
95
+ }
96
+ },
97
+ async reset(key) {
98
+ local.clear(key);
99
+ unpersisted.clear(key);
100
+ await store.delete(key);
101
+ }
102
+ };
103
+ }
104
+ function attemptLimitError(action, key, failures) {
105
+ return new require_errors.SzamlazzError(`Ezt a kérést már ${failures} alkalommal sikertelenül küldtük el, ezért a kassza nem küldi el újra.`, {
106
+ category: "attempt_limit",
107
+ action,
108
+ details: { attemptKey: key },
109
+ hint: "A Számlázz.hu szabályai szerint öt sikertelen próbálkozás után emberi beavatkozás kell, különben kitiltás jöhet. Javítsd a hibát, majd a kassza.resetAttempts(error) hívással töröld a számlálót."
110
+ });
111
+ }
112
+ const DEFAULT_SAFE_ATTEMPTS = 3;
113
+ const DEFAULT_RETRY_DELAY_MS = 1e3;
114
+ const RETRY_JITTER = .2;
115
+ function readEnv(name) {
116
+ const value = (globalThis.process?.env)?.[name]?.trim();
117
+ return value ? value : void 0;
118
+ }
119
+ function configurationError(message) {
120
+ return new require_errors.SzamlazzError(message, { category: "configuration" });
121
+ }
122
+ function resolveCredentials(options) {
123
+ const agentKey = options.agentKey?.trim() || (options.username ? void 0 : readEnv("SZAMLAZZ_AGENT_KEY"));
124
+ if (agentKey) {
125
+ if (agentKey !== agentKey.toLowerCase()) throw configurationError("Az Agent kulcs nagybetűt tartalmaz. A Számlázz.hu csak kisbetűs kulcsot fogad el, másold ki újra a kulcsot.");
126
+ return [require_serialize.el("szamlaagentkulcs", agentKey)];
127
+ }
128
+ if (options.username && options.password) return [require_serialize.el("felhasznalo", options.username), require_serialize.el("jelszo", options.password)];
129
+ throw configurationError("Hiányzik az Agent kulcs. Add meg az agentKey opciót, vagy állítsd be a SZAMLAZZ_AGENT_KEY környezeti változót.");
130
+ }
131
+ function toBlob(attachment) {
132
+ const type = attachment.contentType ?? "application/octet-stream";
133
+ if (attachment.content instanceof Blob) return attachment.content;
134
+ return new Blob([attachment.content], { type });
135
+ }
136
+ function buildFormData(request) {
137
+ const form = new FormData();
138
+ form.append(require_create_once.AGENT_ACTIONS[request.action], new Blob([request.xml], { type: "text/xml; charset=UTF-8" }), "request.xml");
139
+ request.attachments?.forEach((attachment, index) => {
140
+ form.append(`attachfile${index + 1}`, toBlob(attachment), attachment.filename);
141
+ });
142
+ return form;
143
+ }
144
+ function isAbortError(error) {
145
+ return error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
146
+ }
147
+ function sleep(ms, signal) {
148
+ return new Promise((resolve, reject) => {
149
+ if (signal?.aborted) {
150
+ reject(signal.reason);
151
+ return;
152
+ }
153
+ const timer = setTimeout(() => {
154
+ signal?.removeEventListener("abort", onAbort);
155
+ resolve();
156
+ }, ms);
157
+ const onAbort = () => {
158
+ clearTimeout(timer);
159
+ reject(signal?.reason);
160
+ };
161
+ signal?.addEventListener("abort", onAbort, { once: true });
162
+ });
163
+ }
164
+ function hookWarning(name, action, error) {
165
+ return {
166
+ kind: "hook",
167
+ message: `A(z) ${name} hook hibát dobott, a kassza figyelmen kívül hagyta.`,
168
+ error,
169
+ action,
170
+ operation: name
171
+ };
172
+ }
173
+ function callHook(hooks, name, event) {
174
+ const hook = hooks[name];
175
+ if (!hook) return;
176
+ try {
177
+ const result = hook(event);
178
+ if (result instanceof Promise) result.catch((error) => require_warnings.emitWarning(hooks.onWarning, hookWarning(name, event.action, error)));
179
+ } catch (error) {
180
+ require_warnings.emitWarning(hooks.onWarning, hookWarning(name, event.action, error));
181
+ }
182
+ }
183
+ function parseRetryAfter(value, now) {
184
+ if (value === null) return void 0;
185
+ const trimmed = value.trim();
186
+ if (/^\d+$/.test(trimmed)) return Number(trimmed) * 1e3;
187
+ const date = Date.parse(trimmed);
188
+ if (Number.isNaN(date)) return void 0;
189
+ return Math.max(0, date - now);
190
+ }
191
+ function retryDelay(baseMs, attempt, random = Math.random()) {
192
+ const backoff = baseMs * 2 ** (attempt - 1);
193
+ return Math.round(backoff * (.8 + 2 * RETRY_JITTER * random));
194
+ }
195
+ function resolveLedgerMode(value) {
196
+ if (value === void 0 || value === "fail-open" || value === "fail-closed") return value ?? "fail-open";
197
+ throw configurationError(`Az attemptLedgerMode értéke 'fail-open' vagy 'fail-closed' lehet, kapott: ${String(value)}`);
198
+ }
199
+ function storeUnavailableError(action, error) {
200
+ return new require_errors.SzamlazzError("A próbálkozás-napló tárolója nem érhető el, ezért a kassza nem küldte el a kérést.", {
201
+ category: "store_unavailable",
202
+ action,
203
+ cause: error,
204
+ hint: "Az attemptLedgerMode: 'fail-closed' beállítás miatt a kassza nem küld kérést, amíg a napló (például a Redis) nem elérhető. Állítsd helyre a tárolót, vagy válts 'fail-open' módra."
205
+ });
206
+ }
207
+ function clampAttempts(value) {
208
+ if (value === void 0) return DEFAULT_SAFE_ATTEMPTS;
209
+ if (!Number.isInteger(value) || value < 1) throw configurationError(`A maxAttempts értéke legalább 1 egész szám legyen, kapott: ${value}`);
210
+ return Math.min(value, 5);
211
+ }
212
+ function resolveCooldown(value) {
213
+ if (value === void 0) return 0;
214
+ if (!Number.isFinite(value) || value < 0) throw configurationError(`A maintenanceCooldownMs értéke nemnegatív szám legyen, kapott: ${value}`);
215
+ return value;
216
+ }
217
+ function attachmentSize(attachment) {
218
+ const { content } = attachment;
219
+ if (typeof content === "string") return new TextEncoder().encode(content).byteLength;
220
+ if (content instanceof Blob) return content.size;
221
+ return content.byteLength;
222
+ }
223
+ function maintenanceCooldownError(action, remainingMs) {
224
+ return new require_errors.SzamlazzError(`A Számlázz.hu karbantartás miatt nem érhető el, a kassza még ${Math.ceil(remainingMs / 1e3)} másodpercig nem küld kérést.`, {
225
+ category: "maintenance",
226
+ action,
227
+ hint: "A maintenanceCooldownMs beállítás miatt a kérés el sem indult. Válts tartalék folyamatra (például kézi nyugtatömbre), vagy próbáld később."
228
+ });
229
+ }
230
+ function createAgentContext(options = {}) {
231
+ const credentials = resolveCredentials(options);
232
+ const endpoint = options.endpoint ?? "https://www.szamlazz.hu/szamla/";
233
+ const fetchImpl = options.fetch ?? globalThis.fetch;
234
+ if (typeof fetchImpl !== "function") throw configurationError("Nem található fetch implementáció. Add meg a fetch opciót.");
235
+ const timeoutMs = options.timeoutMs ?? 6e4;
236
+ const safeAttempts = clampAttempts(options.maxAttempts);
237
+ const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
238
+ const cookieStore = options.cookieStore === false ? void 0 : options.cookieStore ?? require_session.memoryCookieStore();
239
+ const sessionSecret = credentials.map((node) => String(node.content)).join("|");
240
+ let sessionKeyPromise;
241
+ const resolveSessionKey = () => {
242
+ sessionKeyPromise ??= require_session.sessionKeyFor(sessionSecret);
243
+ return sessionKeyPromise;
244
+ };
245
+ const hooks = options.hooks ?? {};
246
+ const warn = (warning) => require_warnings.emitWarning(hooks.onWarning, warning);
247
+ const ledger = options.attemptLedger ? createAttemptLedger(options.attemptLedger) : void 0;
248
+ const ledgerMode = resolveLedgerMode(options.attemptLedgerMode);
249
+ async function ignoreStoreFailure(operation, action, run) {
250
+ try {
251
+ return await run();
252
+ } catch (error) {
253
+ warn({
254
+ kind: "session",
255
+ message: `A session cookie tároló "${operation}" művelete sikertelen, a kérés session nélkül folytatódik.`,
256
+ error,
257
+ action,
258
+ operation
259
+ });
260
+ return;
261
+ }
262
+ }
263
+ const cooldownMs = resolveCooldown(options.maintenanceCooldownMs);
264
+ let blockedUntil = 0;
265
+ async function send(request) {
266
+ const cookie = cookieStore ? await ignoreStoreFailure("get", request.action, async () => cookieStore.get(await resolveSessionKey())) : void 0;
267
+ request.signal?.throwIfAborted();
268
+ const headers = new Headers({ Accept: "application/xml, application/pdf, text/plain, */*" });
269
+ if (cookie) headers.set("Cookie", cookie);
270
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
271
+ const signal = request.signal ? AbortSignal.any([request.signal, timeoutSignal]) : timeoutSignal;
272
+ let response;
273
+ let body;
274
+ try {
275
+ response = await fetchImpl(endpoint, {
276
+ method: "POST",
277
+ headers,
278
+ body: buildFormData(request),
279
+ signal
280
+ });
281
+ body = new Uint8Array(await response.arrayBuffer());
282
+ } catch (error) {
283
+ if (request.signal?.aborted) throw request.signal.reason;
284
+ if (timeoutSignal.aborted || isAbortError(error)) throw new require_errors.SzamlazzError(`A Számlázz.hu nem válaszolt ${timeoutMs} ms alatt.`, {
285
+ category: "timeout",
286
+ action: request.action,
287
+ cause: error
288
+ });
289
+ throw new require_errors.SzamlazzError("Hálózati hiba a Számlázz.hu elérésekor.", {
290
+ category: "network",
291
+ action: request.action,
292
+ cause: error
293
+ });
294
+ }
295
+ if (cookieStore) {
296
+ const merged = require_session.mergeSetCookies(cookie, response.headers);
297
+ if (merged) await ignoreStoreFailure("set", request.action, async () => cookieStore.set(await resolveSessionKey(), merged, require_session.SESSION_TTL_SECONDS));
298
+ }
299
+ return {
300
+ response: require_parse.createAgentResponse(request.action, response.status, response.headers, body),
301
+ sessionReused: Boolean(cookie)
302
+ };
303
+ }
304
+ async function resetSession() {
305
+ if (cookieStore) await ignoreStoreFailure("delete", void 0, async () => cookieStore.delete(await resolveSessionKey()));
306
+ }
307
+ async function resetAttempts(key) {
308
+ if (ledger) await ledger.reset(key);
309
+ }
310
+ async function ledgerKeyFor(request) {
311
+ if (!ledger) return void 0;
312
+ return attemptLedgerKey({
313
+ action: request.action,
314
+ xml: request.xml,
315
+ attachments: (request.attachments ?? []).map((attachment) => ({
316
+ filename: attachment.filename,
317
+ size: attachmentSize(attachment)
318
+ }))
319
+ });
320
+ }
321
+ function ledgerWarning(operation, action, error) {
322
+ warn({
323
+ kind: "ledger",
324
+ message: `A próbálkozás-napló tárolójának "${operation}" művelete sikertelen. A kassza a folyamaton belüli számlálót használja, a folyamatok közötti védelem most nem él.`,
325
+ error,
326
+ action,
327
+ operation
328
+ });
329
+ }
330
+ async function readFailures(action, key) {
331
+ if (!ledger || key === void 0) return 0;
332
+ try {
333
+ return await ledger.failures(key);
334
+ } catch (error) {
335
+ if (ledgerMode === "fail-closed") throw storeUnavailableError(action, error);
336
+ ledgerWarning("get", action, error);
337
+ return ledger.fallbackFailures(key);
338
+ }
339
+ }
340
+ async function recordFailure(action, key) {
341
+ if (!ledger || key === void 0) return;
342
+ try {
343
+ await ledger.recordFailure(key);
344
+ } catch (error) {
345
+ ledgerWarning("increment", action, error);
346
+ }
347
+ }
348
+ async function clearFailures(action, key) {
349
+ if (!ledger || key === void 0) return;
350
+ try {
351
+ await ledger.reset(key);
352
+ } catch (error) {
353
+ ledgerWarning("delete", action, error);
354
+ }
355
+ }
356
+ function assertNoCooldown(action) {
357
+ const remainingMs = blockedUntil - Date.now();
358
+ if (remainingMs > 0) throw maintenanceCooldownError(action, remainingMs);
359
+ }
360
+ async function execute(request, parse) {
361
+ const maxAttempts = request.safeToRetry ? safeAttempts : 1;
362
+ const ledgerKey = await ledgerKeyFor(request);
363
+ const requestId = crypto.randomUUID();
364
+ for (let attempt = 1;; attempt++) {
365
+ assertNoCooldown(request.action);
366
+ const failures = await readFailures(request.action, ledgerKey);
367
+ if (ledgerKey !== void 0 && failures >= 5) throw attemptLimitError(request.action, ledgerKey, failures);
368
+ const startedAt = Date.now();
369
+ let retryAfterMs;
370
+ const base = {
371
+ action: request.action,
372
+ attempt,
373
+ requestId
374
+ };
375
+ callHook(hooks, "onRequest", base);
376
+ try {
377
+ const { response, sessionReused } = await send(request);
378
+ retryAfterMs = parseRetryAfter(response.headers.get("retry-after"), Date.now());
379
+ callHook(hooks, "onResponse", {
380
+ ...base,
381
+ status: response.status,
382
+ durationMs: Date.now() - startedAt,
383
+ responseBytes: response.body.byteLength,
384
+ sessionReused
385
+ });
386
+ const result = await parse(response);
387
+ if (failures > 0) await clearFailures(request.action, ledgerKey);
388
+ callHook(hooks, "onComplete", {
389
+ ...base,
390
+ outcome: "success",
391
+ durationMs: Date.now() - startedAt,
392
+ willRetry: false
393
+ });
394
+ return result;
395
+ } catch (error) {
396
+ if (!(error instanceof require_errors.SzamlazzError)) {
397
+ callHook(hooks, "onComplete", {
398
+ ...base,
399
+ outcome: "error",
400
+ durationMs: Date.now() - startedAt,
401
+ willRetry: false
402
+ });
403
+ throw error;
404
+ }
405
+ if (countsAsFailedAttempt(error)) await recordFailure(request.action, ledgerKey);
406
+ if (error.category === "maintenance" && cooldownMs > 0) blockedUntil = Date.now() + cooldownMs;
407
+ const willRetry = error.retryable && attempt < maxAttempts && !(error.category === "maintenance" && cooldownMs > 0) && (retryAfterMs === void 0 || retryAfterMs <= 6e4);
408
+ callHook(hooks, "onError", {
409
+ ...base,
410
+ error,
411
+ willRetry
412
+ });
413
+ callHook(hooks, "onComplete", {
414
+ ...base,
415
+ outcome: "error",
416
+ durationMs: Date.now() - startedAt,
417
+ error,
418
+ willRetry
419
+ });
420
+ if (error.category === "auth") await resetSession();
421
+ if (!willRetry) throw error;
422
+ await sleep(Math.max(retryDelay(retryDelayMs, attempt), retryAfterMs ?? 0), request.signal);
423
+ }
424
+ }
425
+ }
426
+ return {
427
+ credentials,
428
+ warn,
429
+ execute,
430
+ resetSession,
431
+ resetAttempts
432
+ };
433
+ }
434
+ //#endregion
435
+ //#region src/invoices/create-response.ts
436
+ function readRawResponse(response) {
437
+ require_parse.throwIfAnyError(response);
438
+ const headers = require_parse.readDocumentHeaders(response.headers);
439
+ const fromHeaders = {
440
+ number: headers.number,
441
+ netTotal: headers.netTotal,
442
+ grossTotal: headers.grossTotal,
443
+ outstanding: void 0,
444
+ buyerAccountUrl: headers.buyerAccountUrl,
445
+ pdf: void 0
446
+ };
447
+ if (response.isPdf) return {
448
+ ...fromHeaders,
449
+ pdf: response.body
450
+ };
451
+ if (require_parse.looksLikeXml(response)) {
452
+ const root = require_parse.parseResponseXml(response);
453
+ require_parse.throwIfXmlFailure(root, response);
454
+ const pdfBase64 = require_serialize.childText(root, "pdf");
455
+ return {
456
+ number: require_serialize.childText(root, "szamlaszam") ?? headers.number,
457
+ netTotal: require_serialize.childNumber(root, "szamlanetto") ?? headers.netTotal,
458
+ grossTotal: require_serialize.childNumber(root, "szamlabrutto") ?? headers.grossTotal,
459
+ outstanding: require_serialize.childNumber(root, "kintlevoseg"),
460
+ buyerAccountUrl: require_serialize.childText(root, "vevoifiokurl") ?? headers.buyerAccountUrl,
461
+ pdf: pdfBase64 === void 0 ? void 0 : require_binary.base64ToBytes(pdfBase64)
462
+ };
463
+ }
464
+ const done = require_parse.parseDoneText(response.text());
465
+ if (done) return {
466
+ ...fromHeaders,
467
+ number: done.number ?? headers.number
468
+ };
469
+ if (headers.number !== void 0) return fromHeaders;
470
+ throw require_parse.unexpectedResponse(response, "Számlaszámot vagy PDF-et vártunk.");
471
+ }
472
+ function totalsFor(raw, items) {
473
+ if (raw.netTotal !== void 0 && raw.grossTotal !== void 0) return {
474
+ netTotal: raw.netTotal,
475
+ grossTotal: raw.grossTotal
476
+ };
477
+ const computed = require_money.summarizeItems(items);
478
+ return {
479
+ netTotal: raw.netTotal ?? computed.netAmount,
480
+ grossTotal: raw.grossTotal ?? computed.grossAmount
481
+ };
482
+ }
483
+ function parseCreateInvoiceResponse(response, items = []) {
484
+ const raw = readRawResponse(response);
485
+ if (raw.number === void 0) throw require_parse.unexpectedResponse(response, "A sikeres válaszból hiányzik a számlaszám.");
486
+ return {
487
+ number: raw.number,
488
+ ...totalsFor(raw, items),
489
+ outstanding: raw.outstanding,
490
+ buyerAccountUrl: raw.buyerAccountUrl,
491
+ pdf: raw.pdf,
492
+ items
493
+ };
494
+ }
495
+ function parseInvoicePreviewResponse(response, items = []) {
496
+ const raw = readRawResponse(response);
497
+ if (raw.pdf === void 0) throw require_parse.unexpectedResponse(response, "Az előnézeti válaszból hiányzik a PDF.");
498
+ return {
499
+ pdf: raw.pdf,
500
+ ...totalsFor(raw, items),
501
+ items
502
+ };
503
+ }
504
+ //#endregion
505
+ //#region src/invoices/create-xml.ts
506
+ const INVOICE_XML_NAMESPACE = "http://www.szamlazz.hu/xmlszamla";
507
+ const INVOICE_XML_SCHEMA_LOCATION = "https://www.szamlazz.hu/szamla/docs/xsds/agent/xmlszamla.xsd";
508
+ const RESPONSE_VERSION_XML = 2;
509
+ function textEl(name, value) {
510
+ return require_serialize.optionalEl(name, require_create_once.presentText(value));
511
+ }
512
+ function settingsNode(credentials, invoice, preview) {
513
+ return require_serialize.el("beallitasok", [
514
+ ...credentials,
515
+ require_serialize.el("eszamla", invoice.eInvoice),
516
+ require_serialize.el("szamlaLetoltes", preview || invoice.downloadPdf),
517
+ require_serialize.el("valaszVerzio", RESPONSE_VERSION_XML),
518
+ textEl("aggregator", invoice.aggregator),
519
+ require_serialize.optionalEl("guardian", invoice.guardian),
520
+ require_serialize.optionalEl("cikkazoninvoice", invoice.articleIdentifierInvoice),
521
+ textEl("szamlaKulsoAzon", invoice.input.externalId)
522
+ ]);
523
+ }
524
+ function documentTypeNodes(invoice) {
525
+ const { input, type } = invoice;
526
+ return [
527
+ type === "advance" && require_serialize.el("elolegszamla", true),
528
+ type === "final" && require_serialize.el("vegszamla", true),
529
+ input.type === "final" && textEl("elolegSzamlaszam", input.advanceInvoiceNumber),
530
+ type === "corrective" && require_serialize.el("helyesbitoszamla", true),
531
+ input.type === "corrective" && textEl("helyesbitettSzamlaszam", input.correctedInvoiceNumber),
532
+ type === "proforma" && require_serialize.el("dijbekero", true),
533
+ type === "deliveryNote" && require_serialize.el("szallitolevel", true)
534
+ ];
535
+ }
536
+ function headerNode(invoice, preview) {
537
+ const { input } = invoice;
538
+ return require_serialize.el("fejlec", [
539
+ require_serialize.el("keltDatum", invoice.issueDate),
540
+ require_serialize.el("teljesitesDatum", invoice.fulfillmentDate),
541
+ require_serialize.el("fizetesiHataridoDatum", invoice.dueDate),
542
+ require_serialize.el("fizmod", invoice.paymentMethod),
543
+ require_serialize.el("penznem", invoice.currency),
544
+ require_serialize.el("szamlaNyelve", invoice.language),
545
+ textEl("megjegyzes", input.comment),
546
+ textEl("arfolyamBank", invoice.exchangeBank),
547
+ require_serialize.optionalEl("arfolyam", invoice.exchangeRate),
548
+ textEl("rendelesSzam", input.orderNumber),
549
+ textEl("dijbekeroSzamlaszam", input.proformaNumber),
550
+ ...documentTypeNodes(invoice),
551
+ textEl("logoExtra", invoice.logoExtra),
552
+ textEl("szamlaszamElotag", invoice.prefix),
553
+ require_serialize.optionalEl("fizetendoKorrekcio", input.paymentCorrection),
554
+ require_serialize.optionalEl("fizetve", input.paid),
555
+ require_serialize.optionalEl("arresAfa", input.marginVat),
556
+ require_serialize.optionalEl("eusAfa", invoice.euVat),
557
+ require_serialize.optionalEl("szamlaSablon", invoice.template),
558
+ preview && require_serialize.el("elonezetpdf", true),
559
+ require_serialize.optionalEl("simpleItems", invoice.simpleItems)
560
+ ]);
561
+ }
562
+ function sellerNode(seller) {
563
+ return require_serialize.el("elado", [
564
+ textEl("bank", seller.bank),
565
+ textEl("bankszamlaszam", seller.bankAccount),
566
+ textEl("emailReplyto", seller.emailReplyTo),
567
+ textEl("emailTargy", seller.emailSubject),
568
+ textEl("emailSzoveg", seller.emailText),
569
+ textEl("alairoNeve", seller.signatoryName)
570
+ ]);
571
+ }
572
+ function buyerLedgerNode(ledger) {
573
+ if (!ledger) return void 0;
574
+ return require_serialize.optionalEl("vevoFokonyv", [
575
+ require_serialize.optionalEl("konyvelesDatum", require_create_once.optionalAgentDate(ledger.bookingDate, "buyer.ledger.bookingDate")),
576
+ textEl("vevoAzonosito", ledger.buyerId),
577
+ textEl("vevoFokonyviSzam", ledger.ledgerAccount),
578
+ require_serialize.optionalEl("folyamatosTelj", ledger.continuousFulfillment),
579
+ require_serialize.optionalEl("elszDatumTol", require_create_once.optionalAgentDate(ledger.settlementPeriodStart, "buyer.ledger.settlementPeriodStart")),
580
+ require_serialize.optionalEl("elszDatumIg", require_create_once.optionalAgentDate(ledger.settlementPeriodEnd, "buyer.ledger.settlementPeriodEnd"))
581
+ ]);
582
+ }
583
+ function buyerNode(buyer, sendEmail) {
584
+ const taxpayerType = buyer.taxpayerType;
585
+ return require_serialize.el("vevo", [
586
+ require_serialize.el("nev", buyer.name),
587
+ textEl("orszag", buyer.country),
588
+ require_serialize.el("irsz", buyer.zip),
589
+ require_serialize.el("telepules", buyer.city),
590
+ require_serialize.el("cim", buyer.address),
591
+ textEl("email", buyer.email),
592
+ require_serialize.el("sendEmail", sendEmail),
593
+ require_serialize.optionalEl("adoalany", taxpayerType === void 0 ? void 0 : require_create_once.TAXPAYER_TYPE_CODES[taxpayerType]),
594
+ textEl("adoszam", buyer.taxNumber),
595
+ textEl("csoportazonosito", buyer.groupTaxNumber),
596
+ textEl("adoszamEU", buyer.euTaxNumber),
597
+ textEl("postazasiNev", buyer.postal?.name),
598
+ textEl("postazasiOrszag", buyer.postal?.country),
599
+ textEl("postazasiIrsz", buyer.postal?.zip),
600
+ textEl("postazasiTelepules", buyer.postal?.city),
601
+ textEl("postazasiCim", buyer.postal?.address),
602
+ buyerLedgerNode(buyer.ledger),
603
+ textEl("azonosito", buyer.identifier),
604
+ textEl("alairoNeve", buyer.signatoryName),
605
+ textEl("telefonszam", buyer.phone),
606
+ textEl("megjegyzes", buyer.comment)
607
+ ]);
608
+ }
609
+ function waybillNode(waybill) {
610
+ if (!waybill) return void 0;
611
+ const { transOFlex: tof, pickPackPoint: ppp, sprinter, mpl } = waybill;
612
+ return require_serialize.el("fuvarlevel", [
613
+ textEl("futarSzolgalat", waybill.courier),
614
+ textEl("vonalkod", waybill.barcode),
615
+ textEl("megjegyzes", waybill.comment),
616
+ tof && require_serialize.el("tof", [
617
+ textEl("azonosito", tof.id),
618
+ textEl("shipmentID", tof.shipmentId),
619
+ require_serialize.optionalEl("csomagszam", tof.packageCount),
620
+ textEl("countryCode", tof.countryCode),
621
+ textEl("zip", tof.zip),
622
+ textEl("service", tof.service)
623
+ ]),
624
+ ppp && require_serialize.el("ppp", [textEl("vonalkodPrefix", ppp.barcodePrefix), textEl("vonalkodPostfix", ppp.barcodePostfix)]),
625
+ sprinter && require_serialize.el("sprinter", [
626
+ textEl("azonosito", sprinter.id),
627
+ textEl("feladokod", sprinter.senderCode),
628
+ textEl("iranykod", sprinter.directionCode),
629
+ require_serialize.optionalEl("csomagszam", sprinter.packageCount),
630
+ textEl("vonalkodPostfix", sprinter.barcodePostfix),
631
+ textEl("szallitasiIdo", sprinter.deliveryTime)
632
+ ]),
633
+ mpl && require_serialize.el("mpl", [
634
+ require_serialize.el("vevokod", mpl.customerCode),
635
+ require_serialize.el("vonalkod", mpl.barcode),
636
+ require_serialize.el("tomeg", String(mpl.weight)),
637
+ textEl("kulonszolgaltatasok", mpl.services),
638
+ require_serialize.optionalEl("erteknyilvanitas", mpl.declaredValue)
639
+ ])
640
+ ]);
641
+ }
642
+ function itemLedgerNode(ledger, label) {
643
+ if (!ledger) return void 0;
644
+ return require_serialize.optionalEl("tetelFokonyv", [
645
+ textEl("gazdasagiEsem", ledger.economicEvent),
646
+ textEl("gazdasagiEsemAfa", ledger.vatEconomicEvent),
647
+ textEl("arbevetelFokonyviSzam", ledger.revenueLedgerAccount),
648
+ textEl("afaFokonyviSzam", ledger.vatLedgerAccount),
649
+ require_serialize.optionalEl("elszDatumTol", require_create_once.optionalAgentDate(ledger.settlementPeriodStart, `${label} settlementPeriodStart`)),
650
+ require_serialize.optionalEl("elszDatumIg", require_create_once.optionalAgentDate(ledger.settlementPeriodEnd, `${label} settlementPeriodEnd`))
651
+ ]);
652
+ }
653
+ function itemNode(item, index) {
654
+ const { input, amounts } = item;
655
+ return require_serialize.el("tetel", [
656
+ require_serialize.el("megnevezes", input.name),
657
+ textEl("azonosito", input.identifier),
658
+ require_serialize.el("mennyiseg", amounts.quantity),
659
+ require_serialize.el("mennyisegiEgyseg", item.unit),
660
+ require_serialize.el("nettoEgysegar", amounts.netUnitPrice),
661
+ require_serialize.el("afakulcs", require_vat.formatVatRate(amounts.vat)),
662
+ require_serialize.optionalEl("arresAfaAlap", input.marginVatBase),
663
+ require_serialize.el("nettoErtek", amounts.netAmount),
664
+ require_serialize.el("afaErtek", amounts.vatAmount),
665
+ require_serialize.el("bruttoErtek", amounts.grossAmount),
666
+ textEl("megjegyzes", input.comment),
667
+ itemLedgerNode(input.ledger, `${index + 1}. tétel ledger`),
668
+ require_serialize.optionalEl("torloKod", input.dataDeletionCode)
669
+ ]);
670
+ }
671
+ function renderInvoiceXml(credentials, invoice, options = {}) {
672
+ const preview = options.preview === true;
673
+ return require_serialize.buildXmlDocument({
674
+ root: "xmlszamla",
675
+ namespace: INVOICE_XML_NAMESPACE,
676
+ schemaLocation: INVOICE_XML_SCHEMA_LOCATION,
677
+ children: [
678
+ settingsNode(credentials, invoice, preview),
679
+ headerNode(invoice, preview),
680
+ sellerNode(invoice.seller),
681
+ buyerNode(invoice.input.buyer, invoice.sendEmail),
682
+ waybillNode(invoice.input.waybill),
683
+ require_serialize.el("tetelek", invoice.items.map(itemNode))
684
+ ]
685
+ });
686
+ }
687
+ function buildCreateInvoiceXml(credentials, defaults, input, now = /* @__PURE__ */ new Date()) {
688
+ return renderInvoiceXml(credentials, require_create_once.resolveInvoice(defaults, input, now));
689
+ }
690
+ //#endregion
691
+ //#region src/invoices/create.ts
692
+ function buildRequest(ctx, invoice, preview, options) {
693
+ const xml = renderInvoiceXml(ctx.credentials, invoice, { preview });
694
+ const attachments = preview ? [] : invoice.attachments;
695
+ return {
696
+ action: "createInvoice",
697
+ xml,
698
+ signal: options.signal,
699
+ ...attachments.length > 0 ? { attachments } : {}
700
+ };
701
+ }
702
+ function itemsOf(invoice) {
703
+ return invoice.items.map((item) => item.amounts);
704
+ }
705
+ async function createInvoice(ctx, defaults, input, options = {}) {
706
+ const invoice = require_create_once.resolveInvoice(defaults, input, /* @__PURE__ */ new Date());
707
+ const items = itemsOf(invoice);
708
+ return ctx.execute(buildRequest(ctx, invoice, false, options), (response) => parseCreateInvoiceResponse(response, items));
709
+ }
710
+ async function previewInvoice(ctx, defaults, input, options = {}) {
711
+ const invoice = require_create_once.resolveInvoice(defaults, input, /* @__PURE__ */ new Date());
712
+ const items = itemsOf(invoice);
713
+ return ctx.execute(buildRequest(ctx, invoice, true, options), (response) => parseInvoicePreviewResponse(response, items));
714
+ }
715
+ //#endregion
716
+ //#region src/invoices/pdf.ts
717
+ function buildInvoicePdfXml(credentials, reference) {
718
+ const resolved = require_reference.resolveInvoiceReference(reference);
719
+ return require_serialize.buildXmlDocument({
720
+ root: "xmlszamlapdf",
721
+ namespace: "http://www.szamlazz.hu/xmlszamlapdf",
722
+ schemaLocation: `${require_reference.AGENT_XSD_BASE_URL}agentpdf/xmlszamlapdf.xsd`,
723
+ children: [
724
+ ...credentials,
725
+ require_serialize.optionalEl("szamlaszam", require_reference.referenceValue(resolved, "invoiceNumber")),
726
+ require_serialize.optionalEl("rendelesSzam", require_reference.referenceValue(resolved, "orderNumber")),
727
+ require_serialize.el("valaszVerzio", 2),
728
+ require_serialize.optionalEl("szamlaKulsoAzon", require_reference.referenceValue(resolved, "externalId"))
729
+ ]
730
+ });
731
+ }
732
+ function parseInvoicePdfResponse(response) {
733
+ const { pdf, ...rest } = require_reference.parseInvoiceResult(response);
734
+ if (pdf === void 0 || pdf.length === 0) throw require_parse.unexpectedResponse(response, "A válasz nem tartalmaz PDF-et.");
735
+ return {
736
+ ...rest,
737
+ pdf
738
+ };
739
+ }
740
+ async function getInvoicePdf(ctx, reference, options = {}) {
741
+ const xml = buildInvoicePdfXml(ctx.credentials, reference);
742
+ return ctx.execute({
743
+ action: "getInvoicePdf",
744
+ xml,
745
+ signal: options.signal,
746
+ safeToRetry: true
747
+ }, parseInvoicePdfResponse);
748
+ }
749
+ const RESPONSE_ROOTS = /* @__PURE__ */ new Set(["xmlszamladbkdelvalasz", "xmlszamlavalasz"]);
750
+ const REFERENCE_HINT = "Add meg a díjbekérő számát szövegként, vagy pontosan egyet ezek közül: { proformaNumber }, { orderNumber }.";
751
+ function resolveProformaReference(reference) {
752
+ if (typeof reference === "string") return { proformaNumber: require_reference.requireText(reference, `Üres díjbekérőszám. ${REFERENCE_HINT}`) };
753
+ if (typeof reference !== "object" || reference === null) throw require_reference.validationError(`Érvénytelen díjbekérő-hivatkozás. ${REFERENCE_HINT}`);
754
+ const record = reference;
755
+ const hasNumber = record.proformaNumber !== void 0;
756
+ if (hasNumber === (record.orderNumber !== void 0)) throw require_reference.validationError(`Érvénytelen díjbekérő-hivatkozás. ${REFERENCE_HINT}`);
757
+ return hasNumber ? { proformaNumber: require_reference.requireText(record.proformaNumber, `Üres proformaNumber. ${REFERENCE_HINT}`) } : { orderNumber: require_reference.requireText(record.orderNumber, `Üres orderNumber. ${REFERENCE_HINT}`) };
758
+ }
759
+ function buildDeleteProformaXml(credentials, reference) {
760
+ const resolved = resolveProformaReference(reference);
761
+ return require_serialize.buildXmlDocument({
762
+ root: "xmlszamladbkdel",
763
+ namespace: "http://www.szamlazz.hu/xmlszamladbkdel",
764
+ schemaLocation: "http://www.szamlazz.hu/docs/xsds/szamladbkdel/xmlszamladbkdel.xsd",
765
+ children: [require_serialize.el("beallitasok", [...credentials]), require_serialize.el("fejlec", [require_serialize.optionalEl("szamlaszam", resolved.proformaNumber), require_serialize.optionalEl("rendelesszam", resolved.orderNumber)])]
766
+ });
767
+ }
768
+ function withProformaCategory(error) {
769
+ if (!(error instanceof require_errors.SzamlazzError) || error.code !== 335) return error;
770
+ return new require_errors.SzamlazzError(error.message, {
771
+ category: "not_found",
772
+ code: error.code,
773
+ hint: "A díjbekérő nem létezik, vagy már törölték.",
774
+ action: error.action,
775
+ httpStatus: error.httpStatus,
776
+ rawResponse: error.rawResponse,
777
+ cause: error
778
+ });
779
+ }
780
+ function parseDeleteProformaResponse(response) {
781
+ try {
782
+ require_parse.throwIfHeaderError(response);
783
+ require_parse.throwIfTextError(response);
784
+ require_parse.throwIfHttpError(response);
785
+ const root = require_parse.parseResponseXml(response);
786
+ require_parse.throwIfXmlFailure(root, response);
787
+ if (!RESPONSE_ROOTS.has(root.name) || require_serialize.childText(root, "sikeres")?.toLowerCase() !== "true") throw require_parse.unexpectedResponse(response, "xmlszamladbkdelvalasz XML választ vártunk.");
788
+ } catch (error) {
789
+ throw withProformaCategory(error);
790
+ }
791
+ }
792
+ async function deleteProforma(ctx, reference, options = {}) {
793
+ const xml = buildDeleteProformaXml(ctx.credentials, reference);
794
+ await ctx.execute({
795
+ action: "deleteProforma",
796
+ xml,
797
+ signal: options.signal
798
+ }, parseDeleteProformaResponse);
799
+ }
800
+ const templates = new Set(require_create_once.INVOICE_TEMPLATES);
801
+ function normalizeInput$2(input) {
802
+ return typeof input === "string" ? { invoiceNumber: input } : input;
803
+ }
804
+ function validateTemplate(template) {
805
+ if (template === void 0 || templates.has(template)) return template;
806
+ throw require_reference.validationError(`Ismeretlen számlasablon: ${String(template)}. Lehetséges értékek: ${require_create_once.INVOICE_TEMPLATES.join(", ")}.`);
807
+ }
808
+ function buildReverseInvoiceXml(credentials, input) {
809
+ const options = normalizeInput$2(input);
810
+ const invoiceNumber = require_reference.requireText(options.invoiceNumber, "Add meg a sztornózandó számla számát (invoiceNumber).");
811
+ const email = options.email;
812
+ const buyer = options.buyer;
813
+ return require_serialize.buildXmlDocument({
814
+ root: "xmlszamlast",
815
+ namespace: "http://www.szamlazz.hu/xmlszamlast",
816
+ schemaLocation: `${require_reference.AGENT_XSD_BASE_URL}agentst/xmlszamlast.xsd`,
817
+ children: [
818
+ require_serialize.el("beallitasok", [
819
+ ...credentials,
820
+ require_serialize.el("eszamla", options.eInvoice ?? false),
821
+ require_serialize.el("szamlaLetoltes", options.downloadPdf ?? true),
822
+ require_serialize.el("valaszVerzio", 2),
823
+ require_serialize.optionalEl("szamlaKulsoAzon", require_reference.optionalText(options.externalId))
824
+ ]),
825
+ require_serialize.el("fejlec", [
826
+ require_serialize.el("szamlaszam", invoiceNumber),
827
+ require_serialize.optionalEl("keltDatum", require_reference.optionalAgentDate(options.issueDate, "issueDate")),
828
+ require_serialize.optionalEl("teljesitesDatum", require_reference.optionalAgentDate(options.fulfillmentDate, "fulfillmentDate")),
829
+ require_serialize.optionalEl("megjegyzes", require_reference.optionalText(options.comment)),
830
+ require_serialize.el("tipus", "SS"),
831
+ require_serialize.optionalEl("szamlaSablon", validateTemplate(options.template))
832
+ ]),
833
+ require_serialize.optionalEl("elado", [
834
+ require_serialize.optionalEl("emailReplyto", require_reference.optionalText(email?.replyTo)),
835
+ require_serialize.optionalEl("emailTargy", require_reference.optionalText(email?.subject)),
836
+ require_serialize.optionalEl("emailSzoveg", require_reference.optionalText(email?.text))
837
+ ]),
838
+ require_serialize.optionalEl("vevo", [
839
+ require_serialize.optionalEl("email", require_reference.optionalText(buyer?.email)),
840
+ require_serialize.optionalEl("adoszam", require_reference.optionalText(buyer?.taxNumber)),
841
+ require_serialize.optionalEl("adoszamEU", require_reference.optionalText(buyer?.euTaxNumber))
842
+ ])
843
+ ]
844
+ });
845
+ }
846
+ function parseReverseInvoiceResponse(response, originalInvoiceNumber) {
847
+ const result = require_reference.parseInvoiceResult(response);
848
+ if (result.number === void 0) throw require_parse.unexpectedResponse(response, "A válaszban nincs sztornó számlaszám.");
849
+ if (originalInvoiceNumber !== void 0 && result.number === originalInvoiceNumber.trim()) throw new require_errors.SzamlazzError(`A(z) ${result.number} bizonylat nem lett sztornózva: a Számlázz.hu az eredeti bizonylatot adta vissza.`, {
850
+ category: "validation",
851
+ action: response.action,
852
+ httpStatus: response.status,
853
+ hint: "Díjbekérő és szállítólevél nem sztornózható. Díjbekérőt a deleteProforma függvénnyel törölhetsz."
854
+ });
855
+ return {
856
+ ...result,
857
+ number: result.number
858
+ };
859
+ }
860
+ async function reverseInvoice(ctx, input, options = {}) {
861
+ const invoiceNumber = normalizeInput$2(input).invoiceNumber;
862
+ const xml = buildReverseInvoiceXml(ctx.credentials, input);
863
+ return ctx.execute({
864
+ action: "reverseInvoice",
865
+ xml,
866
+ signal: options.signal
867
+ }, (response) => parseReverseInvoiceResponse(response, invoiceNumber));
868
+ }
869
+ //#endregion
870
+ //#region src/receipts/get.ts
871
+ const GET_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtaget";
872
+ function normalizeInput$1(input) {
873
+ return typeof input === "string" ? { receiptNumber: input } : input;
874
+ }
875
+ function resolveIdentifier(input) {
876
+ const receiptNumber = require_create.optionalText(input.receiptNumber);
877
+ const orderNumber = require_create.optionalText(input.orderNumber);
878
+ if (receiptNumber === void 0 && orderNumber === void 0) throw require_create.receiptValidationError("A nyugta lekérdezéséhez add meg a nyugtaszámot (receiptNumber) vagy a rendelésszámot (orderNumber).");
879
+ if (receiptNumber !== void 0 && orderNumber !== void 0) throw require_create.receiptValidationError("A nyugta lekérdezéséhez a nyugtaszám (receiptNumber) és a rendelésszám (orderNumber) közül csak az egyiket add meg.");
880
+ return {
881
+ receiptNumber,
882
+ orderNumber
883
+ };
884
+ }
885
+ function buildGetReceiptXml(credentials, input) {
886
+ const normalized = normalizeInput$1(input);
887
+ const { receiptNumber, orderNumber } = resolveIdentifier(normalized);
888
+ return require_serialize.buildXmlDocument({
889
+ root: "xmlnyugtaget",
890
+ namespace: GET_RECEIPT_NAMESPACE,
891
+ schemaLocation: `${require_create.RECEIPT_XSD_BASE_URL}nyugtaget/xmlnyugtaget.xsd`,
892
+ children: [require_serialize.el("beallitasok", [...credentials, require_serialize.el("pdfLetoltes", normalized.downloadPdf ?? true)]), require_serialize.el("fejlec", [
893
+ require_serialize.optionalEl("nyugtaszam", receiptNumber),
894
+ require_serialize.optionalEl("rendelesSzam", orderNumber),
895
+ require_serialize.optionalEl("hivasAzonosito", require_create.optionalText(normalized.callId)),
896
+ require_serialize.optionalEl("pdfSablon", require_create.validateTemplate(normalized.template))
897
+ ])]
898
+ });
899
+ }
900
+ function getReceipt(ctx, input, options = {}) {
901
+ const xml = buildGetReceiptXml(ctx.credentials, input);
902
+ return ctx.execute({
903
+ action: "getReceipt",
904
+ xml,
905
+ signal: options.signal,
906
+ safeToRetry: true
907
+ }, require_parse.parseReceiptResponse);
908
+ }
909
+ //#endregion
910
+ //#region src/receipts/reverse.ts
911
+ const REVERSE_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtast";
912
+ function normalizeInput(input) {
913
+ return typeof input === "string" ? { receiptNumber: input } : input;
914
+ }
915
+ function buildReverseReceiptXml(credentials, input) {
916
+ const normalized = normalizeInput(input);
917
+ return require_serialize.buildXmlDocument({
918
+ root: "xmlnyugtast",
919
+ namespace: REVERSE_RECEIPT_NAMESPACE,
920
+ schemaLocation: `${require_create.RECEIPT_XSD_BASE_URL}nyugtast/xmlnyugtast.xsd`,
921
+ children: [require_serialize.el("beallitasok", [...credentials, require_serialize.el("pdfLetoltes", normalized.downloadPdf ?? true)]), require_serialize.el("fejlec", [
922
+ require_serialize.el("nyugtaszam", require_create.requireReceiptNumber(normalized.receiptNumber)),
923
+ require_serialize.optionalEl("pdfSablon", require_create.validateTemplate(normalized.template)),
924
+ require_serialize.optionalEl("hivasAzonosito", require_create.optionalText(normalized.callId))
925
+ ])]
926
+ });
927
+ }
928
+ function reverseReceipt(ctx, input, options = {}) {
929
+ const normalized = normalizeInput(input);
930
+ const xml = buildReverseReceiptXml(ctx.credentials, normalized);
931
+ return ctx.execute({
932
+ action: "reverseReceipt",
933
+ xml,
934
+ signal: options.signal,
935
+ safeToRetry: require_create.optionalText(normalized.callId) !== void 0
936
+ }, require_parse.parseReceiptResponse);
937
+ }
938
+ //#endregion
939
+ //#region src/receipts/send.ts
940
+ const SEND_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtasend";
941
+ const EMAIL_PATTERN = /^[^\s@,;<>]+@[^\s@,;<>]+\.[^\s@,;<>]+$/;
942
+ function isValidEmail(value) {
943
+ return EMAIL_PATTERN.test(value);
944
+ }
945
+ function assertEmail(value, field) {
946
+ if (!isValidEmail(value)) throw require_create.receiptValidationError(`Érvénytelen e-mail cím a(z) ${field} mezőben: ${value}`);
947
+ return value;
948
+ }
949
+ function normalizeEmails(emails) {
950
+ const list = (typeof emails === "string" ? [emails] : [...emails]).flatMap((entry) => entry.split(/[,;]/)).map((entry) => entry.trim()).filter((entry) => entry !== "");
951
+ if (list.length === 0) throw require_create.receiptValidationError("Adj meg legalább egy címzett e-mail címet (emails).");
952
+ return list.map((email) => assertEmail(email, "emails"));
953
+ }
954
+ function buildSendReceiptXml(credentials, input) {
955
+ const receiptNumber = require_create.requireReceiptNumber(input.receiptNumber);
956
+ const emails = normalizeEmails(input.emails);
957
+ const replyTo = require_create.optionalText(input.replyTo);
958
+ if (replyTo !== void 0) assertEmail(replyTo, "replyTo");
959
+ return require_serialize.buildXmlDocument({
960
+ root: "xmlnyugtasend",
961
+ namespace: SEND_RECEIPT_NAMESPACE,
962
+ schemaLocation: `${require_create.RECEIPT_XSD_BASE_URL}nyugtasend/xmlnyugtasend.xsd`,
963
+ children: [
964
+ require_serialize.el("beallitasok", credentials),
965
+ require_serialize.el("fejlec", [require_serialize.el("nyugtaszam", receiptNumber)]),
966
+ require_serialize.el("emailKuldes", [
967
+ require_serialize.el("email", emails.join(",")),
968
+ require_serialize.optionalEl("emailReplyto", replyTo),
969
+ require_serialize.el("emailTargy", require_create.optionalText(input.subject) ?? `Nyugta ${receiptNumber}`),
970
+ require_serialize.optionalEl("emailSzoveg", input.text?.trim() ? input.text : void 0)
971
+ ])
972
+ ]
973
+ });
974
+ }
975
+ function parseSendReceiptResponse(response) {
976
+ require_parse.throwIfHeaderError(response);
977
+ require_parse.throwIfTextError(response);
978
+ if (!require_parse.looksLikeXml(response)) {
979
+ require_parse.throwIfHttpError(response);
980
+ if (require_parse.parseDoneText(response.text())) return;
981
+ throw require_parse.unexpectedResponse(response, "XML választ vártunk a nyugta kiküldésére.");
982
+ }
983
+ const root = require_parse.parseResponseXml(response);
984
+ require_parse.throwIfXmlFailure(root, response);
985
+ if (require_serialize.childBoolean(root, "sikeres") !== true) {
986
+ require_parse.throwIfHttpError(response);
987
+ throw require_parse.unexpectedResponse(response, "A válasz nem jelez sikeres kiküldést.");
988
+ }
989
+ }
990
+ function sendReceipt(ctx, input, options = {}) {
991
+ const xml = buildSendReceiptXml(ctx.credentials, input);
992
+ return ctx.execute({
993
+ action: "sendReceipt",
994
+ xml,
995
+ signal: options.signal
996
+ }, parseSendReceiptResponse);
997
+ }
998
+ //#endregion
999
+ //#region src/taxpayer/address.ts
1000
+ const ROMAN_NUMERAL = /^[IVX]{1,5}\.?$/;
1001
+ function isShouting(value) {
1002
+ return value === value.toUpperCase() && value !== value.toLowerCase();
1003
+ }
1004
+ function capitalizeWord(word) {
1005
+ if (ROMAN_NUMERAL.test(word)) return word;
1006
+ return word.split("-").map((part) => part.toLowerCase().replace(/\p{L}/u, (letter) => letter.toUpperCase())).join("-");
1007
+ }
1008
+ function toReadableName(value) {
1009
+ if (value === void 0 || !isShouting(value)) return value;
1010
+ return value.split(" ").map(capitalizeWord).join(" ");
1011
+ }
1012
+ function toLowerIfShouting(value) {
1013
+ return value !== void 0 && isShouting(value) ? value.toLowerCase() : value;
1014
+ }
1015
+ function withOrdinalDot(value) {
1016
+ if (value === void 0) return void 0;
1017
+ return /^\d+$/.test(value) ? `${value}.` : value;
1018
+ }
1019
+ function joinParts(parts) {
1020
+ return parts.filter((part) => part !== void 0 && part !== "").join(" ");
1021
+ }
1022
+ function formatAddress(address) {
1023
+ return [
1024
+ joinParts([address.postalCode, address.city]),
1025
+ joinParts([
1026
+ address.street,
1027
+ address.publicPlaceCategory,
1028
+ withOrdinalDot(address.number),
1029
+ address.building === void 0 ? void 0 : `${address.building} ép.`,
1030
+ address.staircase === void 0 ? void 0 : `${withOrdinalDot(address.staircase)} lh.`,
1031
+ address.floor === void 0 ? void 0 : `${withOrdinalDot(address.floor)} em.`,
1032
+ address.door === void 0 ? void 0 : `${withOrdinalDot(address.door)} ajtó`
1033
+ ]),
1034
+ address.lotNumber === void 0 ? void 0 : `hrsz. ${address.lotNumber}`,
1035
+ address.countryCode === "" || address.countryCode === "HU" ? void 0 : address.countryCode
1036
+ ].filter((part) => part !== void 0 && part !== "").join(", ");
1037
+ }
1038
+ function readDetailedAddress(element) {
1039
+ return {
1040
+ countryCode: require_serialize.childText(element, "countryCode"),
1041
+ region: require_serialize.childText(element, "region"),
1042
+ postalCode: require_serialize.childText(element, "postalCode"),
1043
+ city: require_serialize.childText(element, "city"),
1044
+ streetName: require_serialize.childText(element, "streetName"),
1045
+ publicPlaceCategory: require_serialize.childText(element, "publicPlaceCategory"),
1046
+ number: require_serialize.childText(element, "number"),
1047
+ building: require_serialize.childText(element, "building"),
1048
+ staircase: require_serialize.childText(element, "staircase"),
1049
+ floor: require_serialize.childText(element, "floor"),
1050
+ door: require_serialize.childText(element, "door"),
1051
+ lotNumber: require_serialize.childText(element, "lotNumber")
1052
+ };
1053
+ }
1054
+ function parseTaxpayerAddress(item) {
1055
+ const raw = readDetailedAddress(require_serialize.findChild(item, "taxpayerAddress"));
1056
+ const address = {
1057
+ type: require_serialize.childText(item, "taxpayerAddressType")?.toUpperCase() ?? "",
1058
+ countryCode: raw.countryCode?.toUpperCase() ?? "",
1059
+ region: toReadableName(raw.region),
1060
+ postalCode: raw.postalCode ?? "",
1061
+ city: toReadableName(raw.city) ?? "",
1062
+ street: toReadableName(raw.streetName),
1063
+ publicPlaceCategory: toLowerIfShouting(raw.publicPlaceCategory),
1064
+ number: raw.number,
1065
+ building: raw.building,
1066
+ staircase: raw.staircase,
1067
+ floor: raw.floor,
1068
+ door: raw.door,
1069
+ lotNumber: raw.lotNumber
1070
+ };
1071
+ return {
1072
+ ...address,
1073
+ formatted: formatAddress(address),
1074
+ raw
1075
+ };
1076
+ }
1077
+ //#endregion
1078
+ //#region src/taxpayer/query-taxpayer.ts
1079
+ const TAXPAYER_NAMESPACE = "http://www.szamlazz.hu/xmltaxpayer";
1080
+ const TAXPAYER_SCHEMA_LOCATION = "http://www.szamlazz.hu/docs/xsds/agent/xmltaxpayer.xsd";
1081
+ function toTaxpayerId(taxNumber) {
1082
+ const digits = typeof taxNumber === "string" ? taxNumber.replace(/[\s-]+/g, "").replace(/^HU/i, "") : "";
1083
+ if (!/^(?:\d{8}|\d{11})$/.test(digits)) throw new require_errors.SzamlazzError(`Érvénytelen adószám: "${String(taxNumber)}". Add meg a 8 jegyű törzsszámot vagy a 11 jegyű adószámot (pl. 12345678-2-42).`, {
1084
+ category: "validation",
1085
+ action: "queryTaxpayer"
1086
+ });
1087
+ return digits.slice(0, 8);
1088
+ }
1089
+ function buildQueryTaxpayerXml(credentials, taxNumber) {
1090
+ return require_serialize.buildXmlDocument({
1091
+ root: "xmltaxpayer",
1092
+ namespace: TAXPAYER_NAMESPACE,
1093
+ schemaLocation: TAXPAYER_SCHEMA_LOCATION,
1094
+ children: [require_serialize.el("beallitasok", credentials), require_serialize.el("torzsszam", toTaxpayerId(taxNumber))]
1095
+ });
1096
+ }
1097
+ function throwIfNavError(root, response) {
1098
+ const result = require_serialize.findChild(root, "result");
1099
+ if (require_serialize.childText(result, "funcCode")?.toUpperCase() !== "ERROR") return;
1100
+ const errorCode = require_serialize.childText(result, "errorCode");
1101
+ const code = require_errors.parseErrorCode(errorCode);
1102
+ const message = require_serialize.childText(result, "message");
1103
+ const textCode = code === void 0 ? errorCode : void 0;
1104
+ throw require_errors.createAgentError({
1105
+ code,
1106
+ message: textCode === void 0 ? message : [textCode, message].filter(Boolean).join(": "),
1107
+ action: response.action,
1108
+ httpStatus: response.status,
1109
+ rawResponse: response.text().slice(0, 2e3)
1110
+ });
1111
+ }
1112
+ function readTaxNumber(data) {
1113
+ const detail = require_serialize.findChild(data, "taxNumberDetail");
1114
+ const taxpayerId = require_serialize.childText(detail, "taxpayerId");
1115
+ if (taxpayerId === void 0) return void 0;
1116
+ const vatCode = require_serialize.childText(detail, "vatCode");
1117
+ const countyCode = require_serialize.childText(detail, "countyCode");
1118
+ return {
1119
+ taxpayerId,
1120
+ vatCode,
1121
+ countyCode,
1122
+ formatted: vatCode !== void 0 && countyCode !== void 0 ? `${taxpayerId}-${vatCode}-${countyCode}` : void 0
1123
+ };
1124
+ }
1125
+ function readAddresses(data) {
1126
+ return require_serialize.findChildren(require_serialize.findChild(data, "taxpayerAddressList"), "taxpayerAddressItem").map(parseTaxpayerAddress);
1127
+ }
1128
+ function readRequestId(root) {
1129
+ const requestId = require_serialize.childText(require_serialize.findChild(root, "header"), "requestId");
1130
+ return requestId === "-" ? void 0 : requestId;
1131
+ }
1132
+ function parseQueryTaxpayerResponse(response) {
1133
+ require_parse.throwIfAnyError(response);
1134
+ const root = require_parse.parseResponseXml(response);
1135
+ require_parse.throwIfXmlFailure(root, response);
1136
+ if (root.name !== "QueryTaxpayerResponse") throw require_parse.unexpectedResponse(response, "QueryTaxpayerResponse XML választ vártunk.");
1137
+ throwIfNavError(root, response);
1138
+ const requestId = readRequestId(root);
1139
+ const infoDate = require_serialize.childText(root, "infoDate");
1140
+ const data = require_serialize.findChild(root, "taxpayerData");
1141
+ const validity = require_serialize.childBoolean(root, "taxpayerValidity");
1142
+ if (validity === false || data === void 0) return {
1143
+ valid: validity === true,
1144
+ addresses: [],
1145
+ infoDate,
1146
+ requestId
1147
+ };
1148
+ const addresses = readAddresses(data);
1149
+ return {
1150
+ valid: true,
1151
+ name: require_serialize.childText(data, "taxpayerName"),
1152
+ shortName: require_serialize.childText(data, "taxpayerShortName"),
1153
+ taxNumber: readTaxNumber(data),
1154
+ address: addresses.find((address) => address.type === "HQ") ?? addresses[0],
1155
+ addresses,
1156
+ incorporation: require_serialize.childText(data, "incorporation"),
1157
+ vatGroupMembership: require_serialize.childText(data, "vatGroupMembership"),
1158
+ infoDate,
1159
+ requestId
1160
+ };
1161
+ }
1162
+ async function queryTaxpayer(ctx, taxNumber, options = {}) {
1163
+ const xml = buildQueryTaxpayerXml(ctx.credentials, taxNumber);
1164
+ return ctx.execute({
1165
+ action: "queryTaxpayer",
1166
+ xml,
1167
+ signal: options.signal,
1168
+ safeToRetry: true
1169
+ }, parseQueryTaxpayerResponse);
1170
+ }
1171
+ //#endregion
1172
+ //#region src/taxpayer/cache.ts
1173
+ const TAXPAYER_CACHE_KEY_PREFIX = "szamlazz:taxpayer:";
1174
+ const DEFAULT_TAXPAYER_TTL_SECONDS = 86400;
1175
+ const DEFAULT_TAXPAYER_INVALID_TTL_SECONDS = 600;
1176
+ function positiveSeconds(value, fallback, field) {
1177
+ if (value === void 0) return fallback;
1178
+ if (!Number.isFinite(value) || value < 1) throw new require_errors.SzamlazzError(`A(z) ${field} legalább 1 másodperc legyen, kapott: ${String(value)}`, { category: "configuration" });
1179
+ return Math.ceil(value);
1180
+ }
1181
+ function parseCached(value) {
1182
+ if (typeof value !== "string" || value === "") return void 0;
1183
+ try {
1184
+ const parsed = JSON.parse(value);
1185
+ if (typeof parsed !== "object" || parsed === null) return void 0;
1186
+ const info = parsed;
1187
+ return typeof info.valid === "boolean" && Array.isArray(info.addresses) ? info : void 0;
1188
+ } catch {
1189
+ return;
1190
+ }
1191
+ }
1192
+ function cachedTaxpayerQuery(query, options, warn) {
1193
+ const ttl = positiveSeconds(options.ttlSeconds, DEFAULT_TAXPAYER_TTL_SECONDS, "ttlSeconds");
1194
+ const invalidTtl = positiveSeconds(options.invalidTtlSeconds, 600, "invalidTtlSeconds");
1195
+ const report = (operation, error) => warn?.({
1196
+ kind: "cache",
1197
+ message: `Az adószám-gyorsítótár "${operation}" művelete sikertelen, a kassza a Számlázz.hu-tól kérdez.`,
1198
+ error,
1199
+ action: "queryTaxpayer",
1200
+ operation
1201
+ });
1202
+ return async (taxNumber, requestOptions) => {
1203
+ const key = `${TAXPAYER_CACHE_KEY_PREFIX}${toTaxpayerId(taxNumber)}`;
1204
+ try {
1205
+ const cached = parseCached(await options.store.get(key));
1206
+ if (cached) return cached;
1207
+ } catch (error) {
1208
+ report("get", error);
1209
+ }
1210
+ const info = await query(taxNumber, requestOptions);
1211
+ try {
1212
+ await options.store.set(key, JSON.stringify(info), info.valid ? ttl : invalidTtl);
1213
+ } catch (error) {
1214
+ report("set", error);
1215
+ }
1216
+ return info;
1217
+ };
1218
+ }
1219
+ //#endregion
1220
+ //#region src/client.ts
1221
+ const CREDENTIAL_PROBE_INVOICE_NUMBER = "KASSZA-CREDENTIAL-PROBE-0";
1222
+ async function nullIfNotFound(promise) {
1223
+ try {
1224
+ return await promise;
1225
+ } catch (error) {
1226
+ if (require_errors.isSzamlazzError(error) && (error.isNotFound || error.code === 7)) return null;
1227
+ throw error;
1228
+ }
1229
+ }
1230
+ function attemptKeyOf(target) {
1231
+ if (typeof target === "string") return target;
1232
+ const key = target.details?.attemptKey;
1233
+ if (key === void 0) throw new TypeError("A resetAttempts egy attempt_limit hibát vagy annak details.attemptKey kulcsát várja.");
1234
+ return key;
1235
+ }
1236
+ function invoiceNumberOf(input) {
1237
+ return typeof input === "string" ? input : input.invoiceNumber;
1238
+ }
1239
+ function receiptNumberOf(input) {
1240
+ return typeof input === "string" ? input : input.receiptNumber;
1241
+ }
1242
+ function createDocumentEmitter(hook, options) {
1243
+ return { emit: (event) => require_create_once.emitDocumentEvent(hook, event, options) };
1244
+ }
1245
+ function createInvoicesApi(ctx, defaults, events, guard) {
1246
+ const api = {
1247
+ async create(input, options) {
1248
+ const document = await createInvoice(ctx, defaults, input, options);
1249
+ await events.emit({
1250
+ kind: "invoice",
1251
+ action: "created",
1252
+ number: document.number,
1253
+ document,
1254
+ input
1255
+ });
1256
+ return document;
1257
+ },
1258
+ createOnce: (input, options) => require_issue.createInvoiceOnce(api, input, options, guard),
1259
+ preview: (input, options) => previewInvoice(ctx, defaults, input, options),
1260
+ async reverse(input, options) {
1261
+ const document = await reverseInvoice(ctx, input, options);
1262
+ await events.emit({
1263
+ kind: "invoice",
1264
+ action: "reversed",
1265
+ number: document.number,
1266
+ reversedNumber: invoiceNumberOf(input),
1267
+ document
1268
+ });
1269
+ return document;
1270
+ },
1271
+ async registerPayment(input, options) {
1272
+ const document = await require_create_once.registerPayment(ctx, input, options);
1273
+ await events.emit({
1274
+ kind: "invoice",
1275
+ action: "payment",
1276
+ number: document.invoiceNumber,
1277
+ document
1278
+ });
1279
+ return document;
1280
+ },
1281
+ registerPaymentOnce: (input, options) => require_create_once.registerPaymentOnce(api, input, options, guard),
1282
+ async clearPayments(input, options) {
1283
+ const document = await require_create_once.clearPayments(ctx, input, options);
1284
+ await events.emit({
1285
+ kind: "invoice",
1286
+ action: "payment",
1287
+ number: document.invoiceNumber,
1288
+ document
1289
+ });
1290
+ return document;
1291
+ },
1292
+ getPdf: (reference, options) => getInvoicePdf(ctx, reference, options),
1293
+ get: (reference, query, options) => require_get.getInvoice(ctx, reference, query, options),
1294
+ find: (reference, query, options) => nullIfNotFound(require_get.getInvoice(ctx, reference, query, options)),
1295
+ deleteProforma: (reference, options) => deleteProforma(ctx, reference, options)
1296
+ };
1297
+ return api;
1298
+ }
1299
+ function convertedJoin(result) {
1300
+ return {
1301
+ receipt: result.receipt,
1302
+ invoice: {
1303
+ ...result.invoice,
1304
+ created: false
1305
+ }
1306
+ };
1307
+ }
1308
+ function createReceiptsApi(ctx, defaults, invoices, events, guard) {
1309
+ const api = {
1310
+ async create(input, options) {
1311
+ const document = await require_create.createReceipt(ctx, defaults, input, options);
1312
+ await events.emit({
1313
+ kind: "receipt",
1314
+ action: "created",
1315
+ number: document.number,
1316
+ document
1317
+ });
1318
+ return document;
1319
+ },
1320
+ createOnce: (input, options) => require_create_once.createReceiptOnce(api, input, options, guard),
1321
+ async reverse(input, options) {
1322
+ const document = await reverseReceipt(ctx, input, options);
1323
+ await events.emit({
1324
+ kind: "receipt",
1325
+ action: "reversed",
1326
+ number: document.number,
1327
+ reversedNumber: receiptNumberOf(input),
1328
+ document
1329
+ });
1330
+ return document;
1331
+ },
1332
+ get: (input, options) => getReceipt(ctx, input, options),
1333
+ find: (input, options) => nullIfNotFound(getReceipt(ctx, input, options)),
1334
+ send: (input, options) => sendReceipt(ctx, input, options),
1335
+ convertToInvoice: (input, options = {}) => require_issue.guardOnce(guard, `convert:${input.receiptNumber?.trim() ?? ""}`, {
1336
+ ...options,
1337
+ lock: false
1338
+ }, () => require_issue.convertReceiptToInvoice({
1339
+ receipts: api,
1340
+ invoices
1341
+ }, input, options), convertedJoin)
1342
+ };
1343
+ return api;
1344
+ }
1345
+ function onceScopeOf(ctx) {
1346
+ return ctx.credentials.map((node) => `${node.name}=${String(node.content)}`).join("\n");
1347
+ }
1348
+ function createKassza(options = {}) {
1349
+ const ctx = createAgentContext(options);
1350
+ const events = createDocumentEmitter(options.hooks?.onDocument, {
1351
+ mode: options.hooks?.onDocumentError,
1352
+ onWarning: options.hooks?.onWarning
1353
+ });
1354
+ const guard = {
1355
+ scope: onceScopeOf(ctx),
1356
+ lock: options.createOnceLock,
1357
+ warn: ctx.warn
1358
+ };
1359
+ const directQuery = (taxNumber, requestOptions) => queryTaxpayer(ctx, taxNumber, requestOptions);
1360
+ const taxpayerQuery = options.taxpayerCache ? cachedTaxpayerQuery(directQuery, options.taxpayerCache, ctx.warn) : directQuery;
1361
+ const invoices = createInvoicesApi(ctx, options.defaults?.invoice ?? {}, events, guard);
1362
+ const receipts = createReceiptsApi(ctx, options.defaults?.receipt ?? {}, invoices, events, guard);
1363
+ return {
1364
+ invoices,
1365
+ receipts,
1366
+ taxpayer: { query: taxpayerQuery },
1367
+ async verifyCredentials(requestOptions) {
1368
+ try {
1369
+ await getInvoicePdf(ctx, CREDENTIAL_PROBE_INVOICE_NUMBER, requestOptions);
1370
+ return true;
1371
+ } catch (error) {
1372
+ if (!require_errors.isSzamlazzError(error)) throw error;
1373
+ if (error.category === "auth") return false;
1374
+ if (error.isNotFound || error.code === 7) return true;
1375
+ throw error;
1376
+ }
1377
+ },
1378
+ resetSession: () => ctx.resetSession(),
1379
+ resetAttempts: (target) => ctx.resetAttempts(attemptKeyOf(target)),
1380
+ issueForPayment: (payment, issueOptions) => require_issue.issueForPayment({
1381
+ invoices,
1382
+ receipts
1383
+ }, payment, issueOptions)
1384
+ };
1385
+ }
1386
+ //#endregion
1387
+ Object.defineProperty(exports, "ATTEMPT_LEDGER_KEY_PREFIX", {
1388
+ enumerable: true,
1389
+ get: function() {
1390
+ return ATTEMPT_LEDGER_KEY_PREFIX;
1391
+ }
1392
+ });
1393
+ Object.defineProperty(exports, "ATTEMPT_LEDGER_TTL_SECONDS", {
1394
+ enumerable: true,
1395
+ get: function() {
1396
+ return ATTEMPT_LEDGER_TTL_SECONDS;
1397
+ }
1398
+ });
1399
+ Object.defineProperty(exports, "DEFAULT_TAXPAYER_INVALID_TTL_SECONDS", {
1400
+ enumerable: true,
1401
+ get: function() {
1402
+ return DEFAULT_TAXPAYER_INVALID_TTL_SECONDS;
1403
+ }
1404
+ });
1405
+ Object.defineProperty(exports, "DEFAULT_TAXPAYER_TTL_SECONDS", {
1406
+ enumerable: true,
1407
+ get: function() {
1408
+ return DEFAULT_TAXPAYER_TTL_SECONDS;
1409
+ }
1410
+ });
1411
+ Object.defineProperty(exports, "TAXPAYER_CACHE_KEY_PREFIX", {
1412
+ enumerable: true,
1413
+ get: function() {
1414
+ return TAXPAYER_CACHE_KEY_PREFIX;
1415
+ }
1416
+ });
1417
+ Object.defineProperty(exports, "attemptLedgerKey", {
1418
+ enumerable: true,
1419
+ get: function() {
1420
+ return attemptLedgerKey;
1421
+ }
1422
+ });
1423
+ Object.defineProperty(exports, "buildCreateInvoiceXml", {
1424
+ enumerable: true,
1425
+ get: function() {
1426
+ return buildCreateInvoiceXml;
1427
+ }
1428
+ });
1429
+ Object.defineProperty(exports, "createAgentContext", {
1430
+ enumerable: true,
1431
+ get: function() {
1432
+ return createAgentContext;
1433
+ }
1434
+ });
1435
+ Object.defineProperty(exports, "createKassza", {
1436
+ enumerable: true,
1437
+ get: function() {
1438
+ return createKassza;
1439
+ }
1440
+ });
1441
+ Object.defineProperty(exports, "getInvoicePdf", {
1442
+ enumerable: true,
1443
+ get: function() {
1444
+ return getInvoicePdf;
1445
+ }
1446
+ });
1447
+ Object.defineProperty(exports, "queryTaxpayer", {
1448
+ enumerable: true,
1449
+ get: function() {
1450
+ return queryTaxpayer;
1451
+ }
1452
+ });