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
@@ -1,9 +1,13 @@
1
- import { n as SzamlazzError } from "./errors-DLrb0g64.js";
1
+ import { r as SzamlazzError } from "./errors-DtN4g5Z9.js";
2
2
  import { i as encodeUtf8 } from "./binary-D0M9U2MD.js";
3
- import { S as unknownOutcomeError, b as recoverAfterFailure, x as resolveRecoveryDelay, y as isUncertainOutcome } from "./issue-C6Fcjvln.js";
4
- import { n as toAgentDate, t as addBudapestDays } from "./dates-CXyj7Azy.js";
3
+ import { a as optionalEl, n as buildXmlDocument, r as el } from "./serialize-B2eFh3D-.js";
4
+ import { t as emitWarning } from "./warnings-DwTl5J-2.js";
5
+ import { a as unknownOutcomeError, i as resolveRecoveryDelay, n as isUncertainOutcome, r as recoverAfterFailure } from "./once-CqqZxsXG.js";
6
+ import { m as guardOnce } from "./issue-DMA1Nbr1.js";
7
+ import { a as todayInBudapest, n as toAgentDate, t as addBudapestDays } from "./dates-CXyj7Azy.js";
5
8
  import { i as isHuf } from "./vat-v_dcWCto.js";
6
- import { t as calculateInvoiceItem } from "./money-DAA7OwiO.js";
9
+ import { n as calculateInvoiceItem } from "./money-Cw457SD6.js";
10
+ import { a as optionalText, c as requireText$1, n as agentDate$1, o as parseInvoiceResult, t as AGENT_XSD_BASE_URL, u as validationError } from "./reference-B5TATqb5.js";
7
11
  //#region src/core/actions.ts
8
12
  const SZAMLAZZ_AGENT_URL = "https://www.szamlazz.hu/szamla/";
9
13
  const AGENT_ACTIONS = {
@@ -23,12 +27,47 @@ const AGENT_ACTIONS = {
23
27
  const MAX_INVOICE_ATTACHMENTS = 5;
24
28
  //#endregion
25
29
  //#region src/core/document-events.ts
26
- async function emitDocumentEvent(hook, event) {
30
+ var DocumentHookError = class extends Error {
31
+ name = "DocumentHookError";
32
+ event;
33
+ constructor(event, cause) {
34
+ super(`Az onDocument hook hibát dobott a(z) ${event.number} bizonylatnál. A bizonylat elkészült, csak a hook (például a napló mentése) maradt el: mentsd el újra az error.event alapján, és ne állítsd ki újra a bizonylatot.`, { cause });
35
+ this.event = event;
36
+ }
37
+ get number() {
38
+ return this.event.number;
39
+ }
40
+ get document() {
41
+ return this.event.document;
42
+ }
43
+ };
44
+ function isDocumentHookError(error) {
45
+ return error instanceof DocumentHookError;
46
+ }
47
+ function warnDocumentHook(onWarning, event, error) {
48
+ emitWarning(onWarning, {
49
+ kind: "document",
50
+ message: `Az onDocument hook hibát dobott a(z) ${event.number} bizonylatnál. A bizonylat elkészült, a hiba nem érinti.`,
51
+ error,
52
+ operation: `${event.kind}.${event.action}`
53
+ }, "console");
54
+ }
55
+ async function emitDocumentEvent(hook, event, options = {}) {
27
56
  if (!hook) return;
28
57
  try {
29
58
  await hook(event);
30
59
  } catch (error) {
31
- console.warn(`[szamlazz] Az onDocument hook hibát dobott a(z) ${event.number} bizonylatnál. A bizonylat elkészült, a hiba nem érinti.`, error);
60
+ const mode = options.mode ?? "warn";
61
+ if (mode === "warn") {
62
+ warnDocumentHook(options.onWarning, event, error);
63
+ return;
64
+ }
65
+ if (mode === "throw") throw new DocumentHookError(event, error);
66
+ try {
67
+ await mode(error, event);
68
+ } catch (handlerError) {
69
+ throw new DocumentHookError(event, handlerError);
70
+ }
32
71
  }
33
72
  }
34
73
  //#endregion
@@ -284,6 +323,176 @@ function resolveInvoice(defaults, input, now) {
284
323
  attachments
285
324
  };
286
325
  }
326
+ function normalizeRegisterInput(input) {
327
+ const payments = "payments" in input ? input.payments : [{
328
+ amount: input.amount,
329
+ method: input.method ?? "átutalás",
330
+ date: input.date,
331
+ description: input.description
332
+ }];
333
+ if (!Array.isArray(payments) || payments.length === 0) throw validationError("Adj meg legalább egy befizetést (payments). A korábbi befizetések törléséhez a clearPayments függvényt használd.");
334
+ if (payments.length > 5) throw validationError(`Egy kérésben legfeljebb 5 befizetés rögzíthető, kapott: ${payments.length}.`);
335
+ return {
336
+ invoiceNumber: input.invoiceNumber,
337
+ taxNumber: input.taxNumber,
338
+ additive: input.additive ?? true,
339
+ payments
340
+ };
341
+ }
342
+ function normalizeClearInput(input) {
343
+ const target = typeof input === "string" ? { invoiceNumber: input } : input;
344
+ return {
345
+ invoiceNumber: target.invoiceNumber,
346
+ taxNumber: target.taxNumber,
347
+ additive: false,
348
+ payments: []
349
+ };
350
+ }
351
+ function paymentNode(payment, index) {
352
+ const position = index + 1;
353
+ if (typeof payment.amount !== "number" || !Number.isFinite(payment.amount)) throw validationError(`A(z) ${position}. befizetés összege (amount) nem véges szám.`);
354
+ return el("kifizetes", [
355
+ el("datum", payment.date === void 0 ? todayInBudapest() : agentDate$1(payment.date, "date")),
356
+ el("jogcim", requireText$1(payment.method, `Add meg a(z) ${position}. befizetés módját (method).`)),
357
+ el("osszeg", payment.amount),
358
+ optionalEl("leiras", optionalText(payment.description))
359
+ ]);
360
+ }
361
+ function buildPaymentXml(credentials, request) {
362
+ const invoiceNumber = requireText$1(request.invoiceNumber, "Add meg a számla számát (invoiceNumber), amelyhez a befizetés tartozik.");
363
+ return buildXmlDocument({
364
+ root: "xmlszamlakifiz",
365
+ namespace: "http://www.szamlazz.hu/xmlszamlakifiz",
366
+ schemaLocation: `${AGENT_XSD_BASE_URL}agentkifiz/xmlszamlakifiz.xsd`,
367
+ children: [el("beallitasok", [
368
+ ...credentials,
369
+ el("szamlaszam", invoiceNumber),
370
+ optionalEl("adoszam", optionalText(request.taxNumber)),
371
+ el("additiv", request.additive),
372
+ el("valaszVerzio", 2)
373
+ ]), ...request.payments.map(paymentNode)]
374
+ });
375
+ }
376
+ function parseRegisterPaymentResponse(response, invoiceNumber) {
377
+ const result = parseInvoiceResult(response);
378
+ return {
379
+ invoiceNumber: result.number ?? invoiceNumber.trim(),
380
+ netTotal: result.netTotal,
381
+ grossTotal: result.grossTotal,
382
+ outstanding: result.outstanding,
383
+ buyerAccountUrl: result.buyerAccountUrl
384
+ };
385
+ }
386
+ function sendPaymentRequest(ctx, request, options) {
387
+ const xml = buildPaymentXml(ctx.credentials, request);
388
+ return ctx.execute({
389
+ action: "registerPayment",
390
+ xml,
391
+ signal: options.signal,
392
+ safeToRetry: !request.additive
393
+ }, (response) => parseRegisterPaymentResponse(response, request.invoiceNumber));
394
+ }
395
+ async function registerPayment(ctx, input, options = {}) {
396
+ return sendPaymentRequest(ctx, normalizeRegisterInput(input), options);
397
+ }
398
+ async function clearPayments(ctx, input, options = {}) {
399
+ return sendPaymentRequest(ctx, normalizeClearInput(input), options);
400
+ }
401
+ //#endregion
402
+ //#region src/invoices/payment-once.ts
403
+ const KEY_PATTERN = /^[A-Za-z0-9_.:-]{1,48}$/;
404
+ function validation(message, hint) {
405
+ return new SzamlazzError(message, {
406
+ category: "validation",
407
+ hint
408
+ });
409
+ }
410
+ function paymentMarker(key) {
411
+ const trimmed = key?.trim();
412
+ if (!trimmed || !KEY_PATTERN.test(trimmed)) throw validation(`A registerPaymentOnce kulcsa (key) 1–48 karakter legyen, csak betű, szám és _ . : - jellel, kapott: ${String(key)}`, "Használj rövid, stabil azonosítót, például a banki tranzakció vagy a fizetés azonosítóját.");
413
+ return `[kassza:${trimmed}]`;
414
+ }
415
+ function matchingPayment(details, marker) {
416
+ return details.payments.find((payment) => payment.comment?.includes(marker) === true);
417
+ }
418
+ function describe(description, marker) {
419
+ const text = description?.trim();
420
+ return text ? `${marker} ${text}` : marker;
421
+ }
422
+ function unreadableMarker(invoiceNumber, marker) {
423
+ return new SzamlazzError(`A(z) ${invoiceNumber} számlán a befizetés rögzült, de a jelölő (${marker}) a számla lekérdezésében nem látszik, így a registerPaymentOnce nem tudja megakadályozni az ismételt rögzítést.`, {
424
+ category: "unexpected_response",
425
+ details: {
426
+ invoiceNumber,
427
+ marker,
428
+ registered: "true"
429
+ },
430
+ hint: "NE hívd újra ezt a rögzítést: a befizetés már rögzült. Jelezd a kassza hibajegyében; addig a befizetéseket a saját rendszeredben tartsd nyilván, és a registerPayment-et csak egyszer hívd."
431
+ });
432
+ }
433
+ const QUERY = { includePdf: false };
434
+ async function registerPaymentOnce(api, input, options = {}, guard) {
435
+ const invoiceNumber = input.invoiceNumber?.trim();
436
+ if (!invoiceNumber) throw validation("Add meg a számla számát (invoiceNumber).");
437
+ if (typeof input.amount !== "number" || !Number.isFinite(input.amount) || input.amount === 0) throw validation("A befizetés összege (amount) nullától különböző véges szám legyen.");
438
+ const marker = paymentMarker(input.key);
439
+ const key = input.key.trim();
440
+ const delayMs = resolveRecoveryDelay(options.recoveryDelayMs);
441
+ const lookup = async () => {
442
+ return matchingPayment(await api.get(invoiceNumber, QUERY, options), marker) ?? null;
443
+ };
444
+ const base = {
445
+ invoiceNumber,
446
+ key,
447
+ marker
448
+ };
449
+ const run = async () => {
450
+ const existing = await lookup();
451
+ if (existing) return {
452
+ ...base,
453
+ created: false,
454
+ existing
455
+ };
456
+ let payment;
457
+ try {
458
+ payment = await api.registerPayment({
459
+ invoiceNumber,
460
+ taxNumber: input.taxNumber,
461
+ additive: true,
462
+ amount: input.amount,
463
+ method: input.method ?? "átutalás",
464
+ date: input.date,
465
+ description: describe(input.description, marker)
466
+ }, options);
467
+ } catch (error) {
468
+ if (!isUncertainOutcome(error)) throw error;
469
+ const state = {};
470
+ const recovered = await recoverAfterFailure(lookup, delayMs, options.signal, state);
471
+ if (recovered) return {
472
+ ...base,
473
+ created: true,
474
+ existing: recovered
475
+ };
476
+ throw unknownOutcomeError(error, `${invoiceNumber} számla`, {
477
+ subject: `${key} kulcsú befizetése`,
478
+ lookupError: state.lookupError,
479
+ method: "registerPaymentOnce"
480
+ });
481
+ }
482
+ const confirmed = await lookup();
483
+ if (!confirmed) throw unreadableMarker(invoiceNumber, marker);
484
+ return {
485
+ ...base,
486
+ created: true,
487
+ payment,
488
+ existing: confirmed
489
+ };
490
+ };
491
+ return guardOnce(guard, `payment:${JSON.stringify([invoiceNumber, key])}`, options, run, (result) => ({
492
+ ...result,
493
+ created: false
494
+ }));
495
+ }
287
496
  //#endregion
288
497
  //#region src/receipts/create-once.ts
289
498
  function requireOrderNumber(input) {
@@ -291,7 +500,7 @@ function requireOrderNumber(input) {
291
500
  if (!orderNumber) throw new SzamlazzError("A createOnce-hoz add meg a rendelésszámot (orderNumber), ez azonosítja a nyugtát.", { category: "validation" });
292
501
  return orderNumber;
293
502
  }
294
- async function createReceiptOnce(api, input, options = {}) {
503
+ async function createReceiptOnce(api, input, options = {}, guard) {
295
504
  const orderNumber = requireOrderNumber(input);
296
505
  const callId = input.callId?.trim() || orderNumber;
297
506
  const delayMs = resolveRecoveryDelay(options.recoveryDelayMs);
@@ -299,32 +508,39 @@ async function createReceiptOnce(api, input, options = {}) {
299
508
  orderNumber,
300
509
  downloadPdf: input.downloadPdf
301
510
  }, options);
302
- if (options.lookupFirst !== false) {
303
- const existing = await lookup();
304
- if (existing) return {
305
- receipt: existing,
306
- created: false
307
- };
308
- }
309
- try {
310
- return {
311
- receipt: await api.create({
312
- ...input,
313
- orderNumber,
314
- callId
315
- }, options),
316
- created: true
317
- };
318
- } catch (error) {
319
- if (!isUncertainOutcome(error)) throw error;
320
- const recovered = await recoverAfterFailure(lookup, delayMs, options.signal);
321
- if (recovered) return {
322
- receipt: recovered,
323
- created: error.category !== "duplicate"
324
- };
325
- if (error.category === "duplicate") throw error;
326
- throw unknownOutcomeError(error, `${orderNumber} rendelés`);
327
- }
511
+ const run = async (recheck) => {
512
+ if (recheck || options.lookupFirst !== false) {
513
+ const existing = await lookup();
514
+ if (existing) return {
515
+ receipt: existing,
516
+ created: false
517
+ };
518
+ }
519
+ try {
520
+ return {
521
+ receipt: await api.create({
522
+ ...input,
523
+ orderNumber,
524
+ callId
525
+ }, options),
526
+ created: true
527
+ };
528
+ } catch (error) {
529
+ if (!isUncertainOutcome(error)) throw error;
530
+ const state = {};
531
+ const recovered = await recoverAfterFailure(lookup, delayMs, options.signal, state);
532
+ if (recovered) return {
533
+ receipt: recovered,
534
+ created: error.category !== "duplicate"
535
+ };
536
+ if (error.category === "duplicate" && !state.lookupError) throw error;
537
+ throw unknownOutcomeError(error, `${orderNumber} rendelés`, { lookupError: state.lookupError });
538
+ }
539
+ };
540
+ return guardOnce(guard, `receipt:order:${orderNumber}`, options, run, (result) => ({
541
+ ...result,
542
+ created: false
543
+ }));
328
544
  }
329
545
  //#endregion
330
- export { INVOICE_TEMPLATES as a, AGENT_ACTIONS as c, resolveInvoice as i, MAX_INVOICE_ATTACHMENTS as l, optionalAgentDate as n, TAXPAYER_TYPE_CODES as o, presentText as r, emitDocumentEvent as s, createReceiptOnce as t, SZAMLAZZ_AGENT_URL as u };
546
+ export { SZAMLAZZ_AGENT_URL as _, registerPayment as a, resolveInvoice as c, TAXPAYER_TYPE_CODES as d, DocumentHookError as f, MAX_INVOICE_ATTACHMENTS as g, AGENT_ACTIONS as h, clearPayments as i, INVOICE_LANGUAGES as l, isDocumentHookError as m, paymentMarker as n, optionalAgentDate as o, emitDocumentEvent as p, registerPaymentOnce as r, presentText as s, createReceiptOnce as t, INVOICE_TEMPLATES as u };
@@ -0,0 +1,20 @@
1
+ import { G as InvoiceType, N as CreatedInvoice } from "./context-kb33TgzE.js";
2
+ import { r as Receipt } from "./types-D1zDOH_F.js";
3
+ import { n as InvoiceDetails } from "./get-Byc9T5WO.js";
4
+ //#region src/invoices/create-once.d.ts
5
+ interface InvoiceOnceResult {
6
+ readonly number: string;
7
+ readonly created: boolean;
8
+ readonly externalId: string;
9
+ readonly invoice?: CreatedInvoice | undefined;
10
+ readonly details?: InvoiceDetails | undefined;
11
+ }
12
+ declare function invoiceOnceExternalId(type: InvoiceType, orderNumber: string): string;
13
+ //#endregion
14
+ //#region src/receipts/create-once.d.ts
15
+ interface ReceiptOnceResult {
16
+ readonly receipt: Receipt;
17
+ readonly created: boolean;
18
+ }
19
+ //#endregion
20
+ export { InvoiceOnceResult as n, invoiceOnceExternalId as r, ReceiptOnceResult as t };
@@ -11,6 +11,9 @@ function bytesToHex(bytes) {
11
11
  for (const byte of bytes) hex += byte.toString(16).padStart(2, "0");
12
12
  return hex;
13
13
  }
14
+ async function digestHex(algorithm, data) {
15
+ return bytesToHex(new Uint8Array(await crypto.subtle.digest(algorithm, toBytes(data))));
16
+ }
14
17
  async function hmac(algorithm, key, data) {
15
18
  const cryptoKey = await crypto.subtle.importKey("raw", toBytes(key), {
16
19
  name: "HMAC",
@@ -36,6 +39,12 @@ Object.defineProperty(exports, "bytesToHex", {
36
39
  return bytesToHex;
37
40
  }
38
41
  });
42
+ Object.defineProperty(exports, "digestHex", {
43
+ enumerable: true,
44
+ get: function() {
45
+ return digestHex;
46
+ }
47
+ });
39
48
  Object.defineProperty(exports, "hmac", {
40
49
  enumerable: true,
41
50
  get: function() {
@@ -11,6 +11,9 @@ function bytesToHex(bytes) {
11
11
  for (const byte of bytes) hex += byte.toString(16).padStart(2, "0");
12
12
  return hex;
13
13
  }
14
+ async function digestHex(algorithm, data) {
15
+ return bytesToHex(new Uint8Array(await crypto.subtle.digest(algorithm, toBytes(data))));
16
+ }
14
17
  async function hmac(algorithm, key, data) {
15
18
  const cryptoKey = await crypto.subtle.importKey("raw", toBytes(key), {
16
19
  name: "HMAC",
@@ -30,4 +33,4 @@ function timingSafeEqual(left, right) {
30
33
  return difference === 0;
31
34
  }
32
35
  //#endregion
33
- export { timingSafeEqual as i, hmac as n, hmacHex as r, bytesToHex as t };
36
+ export { timingSafeEqual as a, hmacHex as i, digestHex as n, hmac as r, bytesToHex as t };
@@ -0,0 +1,232 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
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_get = require("../get-BdMTseh4.cjs");
7
+ const require_crypto = require("../crypto-Dpn4FHQ6.cjs");
8
+ const require_request_body = require("../request-body-CH6ZGOrq.cjs");
9
+ //#region src/data-link/push.ts
10
+ var DataLinkError = class extends Error {
11
+ name = "DataLinkError";
12
+ reason;
13
+ constructor(reason, message, cause) {
14
+ super(message, cause === void 0 ? void 0 : { cause });
15
+ this.reason = reason;
16
+ }
17
+ };
18
+ const ROOT_KINDS = /* @__PURE__ */ new Map([
19
+ ["szamla", "invoice"],
20
+ ["szamlabe", "incoming-invoice"],
21
+ ["banktranz", "bank-transaction"],
22
+ ["xmlnyugtaarchiv", "receipts"]
23
+ ]);
24
+ function invalid(message, cause) {
25
+ return new DataLinkError("invalid_payload", message, cause);
26
+ }
27
+ function requiredText(element, name, path) {
28
+ const value = require_serialize.childText(element, name);
29
+ if (value === void 0) throw invalid(`Hiányzik a(z) <${path}/${name}> elem.`);
30
+ return value;
31
+ }
32
+ function requiredInteger(element, name, path) {
33
+ const value = Number(requiredText(element, name, path));
34
+ if (!Number.isInteger(value)) throw invalid(`A(z) <${path}/${name}> nem egész szám.`);
35
+ return value;
36
+ }
37
+ function wrapSzamlazzError(read) {
38
+ try {
39
+ return read();
40
+ } catch (error) {
41
+ if (error instanceof require_errors.SzamlazzError) throw invalid(error.message, error);
42
+ throw error;
43
+ }
44
+ }
45
+ function invoicePush(kind, root, raw, key) {
46
+ const header = require_serialize.findChild(root, "alap");
47
+ const id = requiredInteger(header, "id", "alap");
48
+ const response = require_parse.createAgentResponse("getInvoiceXml", 200, new Headers(), require_binary.encodeUtf8(raw));
49
+ return {
50
+ kind,
51
+ key,
52
+ raw,
53
+ id,
54
+ invoice: wrapSzamlazzError(() => require_get.parseInvoiceDetailsXml(root, response)),
55
+ deleted: require_serialize.childBoolean(header, "dobdel") === true
56
+ };
57
+ }
58
+ function bankTransactionPush(root, raw, key) {
59
+ const direction = requiredText(root, "irany", "banktranz");
60
+ if (direction !== "BE" && direction !== "KI") throw invalid(`Ismeretlen banki tranzakció irány: ${direction}.`);
61
+ const amount = require_serialize.childNumber(root, "osszeg");
62
+ if (amount === void 0) throw invalid("Hiányzik a(z) <banktranz/osszeg> elem.");
63
+ const partner = require_serialize.findChild(root, "partner");
64
+ return {
65
+ kind: "bank-transaction",
66
+ key,
67
+ raw,
68
+ transaction: {
69
+ id: requiredInteger(root, "id", "banktranz"),
70
+ accountNumber: requiredText(root, "bankszamla", "banktranz"),
71
+ valueDate: requiredText(root, "erteknap", "banktranz"),
72
+ direction: direction === "BE" ? "in" : "out",
73
+ type: require_serialize.childText(root, "tipus"),
74
+ technical: require_serialize.childBoolean(root, "technikai") === true,
75
+ amount,
76
+ currency: requiredText(root, "devizanem", "banktranz"),
77
+ partner: partner && {
78
+ name: require_serialize.childText(partner, "nev"),
79
+ accountNumber: require_serialize.childText(partner, "bankszamla")
80
+ },
81
+ reference: require_serialize.childText(root, "kozlemeny")
82
+ }
83
+ };
84
+ }
85
+ function receiptsPush(root, raw, key) {
86
+ const response = require_parse.createAgentResponse("getReceipt", 200, new Headers(), require_binary.encodeUtf8(raw));
87
+ const receipts = require_serialize.findChildren(root, "nyugta").map((element) => ({
88
+ receipt: wrapSzamlazzError(() => require_parse.parseReceiptElement(element, response)),
89
+ issuerTaxNumber: require_serialize.childText(require_serialize.findChild(element, "alap"), "adoszam")
90
+ }));
91
+ if (receipts.length === 0) throw invalid("A nyugtaarchívum nem tartalmaz <nyugta> elemet.");
92
+ return {
93
+ kind: "receipts",
94
+ key,
95
+ raw,
96
+ receipts
97
+ };
98
+ }
99
+ function parseDataLinkPush(xml, key) {
100
+ if (xml.trim() === "") throw invalid("Üres adatkapcsolati üzenet érkezett.");
101
+ let root;
102
+ try {
103
+ root = require_serialize.parseXml(xml);
104
+ } catch (error) {
105
+ if (error instanceof require_serialize.XmlParseError) throw invalid(`Az üzenet nem érvényes XML: ${error.message}`, error);
106
+ throw error;
107
+ }
108
+ const kind = ROOT_KINDS.get(root.name);
109
+ const normalizedKey = key?.trim() || void 0;
110
+ switch (kind) {
111
+ case "invoice":
112
+ case "incoming-invoice": return invoicePush(kind, root, xml, normalizedKey);
113
+ case "bank-transaction": return bankTransactionPush(root, xml, normalizedKey);
114
+ case "receipts": return receiptsPush(root, xml, normalizedKey);
115
+ default: throw new DataLinkError("unknown_document", `Ismeretlen adatkapcsolati bizonylattípus: <${root.name}>.`);
116
+ }
117
+ }
118
+ //#endregion
119
+ //#region src/data-link/response.ts
120
+ const DATA_LINK_RESPONSE_ROOTS = {
121
+ invoice: {
122
+ root: "szamlavalasz",
123
+ namespace: "http://www.szamlazz.hu/szamlavalasz"
124
+ },
125
+ "incoming-invoice": {
126
+ root: "szamlabevalasz",
127
+ namespace: "http://www.szamlazz.hu/szamlabevalasz"
128
+ },
129
+ "bank-transaction": {
130
+ root: "banktranzvalasz",
131
+ namespace: "http://www.szamlazz.hu/banktranzvalasz"
132
+ },
133
+ receipts: {
134
+ root: "nyugtavalasz",
135
+ namespace: "http://www.szamlazz.hu/nyugtavalasz"
136
+ }
137
+ };
138
+ function keyErrorOf(acknowledgement) {
139
+ const keyError = acknowledgement.keyError;
140
+ if (keyError === void 0 || keyError === "KEY_ERR" || keyError === "KEY_DEL") return keyError;
141
+ throw new TypeError(`Ismeretlen kulcshiba: ${String(keyError)}. Csak KEY_ERR vagy KEY_DEL adható.`);
142
+ }
143
+ function registrationNumberOf(push, value) {
144
+ if (value !== void 0 && typeof value !== "string") throw new TypeError("Az iktatószám (registrationNumber) szöveg legyen.");
145
+ const registrationNumber = value?.trim();
146
+ if (!registrationNumber) return void 0;
147
+ if (push.kind !== "invoice" && push.kind !== "incoming-invoice") throw new TypeError("Iktatószámot csak számla (kimenő vagy bejövő) válaszában lehet visszaadni.");
148
+ return registrationNumber;
149
+ }
150
+ function dataLinkResponseXml(push, acknowledgement = {}) {
151
+ const target = DATA_LINK_RESPONSE_ROOTS[push.kind];
152
+ const keyError = keyErrorOf(acknowledgement);
153
+ const registrationNumber = registrationNumberOf(push, acknowledgement.registrationNumber);
154
+ const children = [];
155
+ if (push.kind === "invoice" || push.kind === "incoming-invoice") children.push(require_serialize.el("alap", [require_serialize.el("id", push.id), require_serialize.optionalEl("iktatoszam", registrationNumber)]));
156
+ if (keyError !== void 0) children.push(require_serialize.el("hibakod", keyError));
157
+ return require_serialize.buildXmlDocument({
158
+ root: target.root,
159
+ namespace: target.namespace,
160
+ children
161
+ });
162
+ }
163
+ function dataLinkResponse(push, acknowledgement = {}) {
164
+ return new Response(dataLinkResponseXml(push, acknowledgement), {
165
+ status: 200,
166
+ headers: { "content-type": "application/xml; charset=UTF-8" }
167
+ });
168
+ }
169
+ //#endregion
170
+ //#region src/data-link/handler.ts
171
+ const DATA_LINK_KEY_HEADER = "x-szamlazzhu-key";
172
+ const DEFAULT_DATA_LINK_MAX_BYTES = 67108864;
173
+ function plain(status, body) {
174
+ return new Response(body, {
175
+ status,
176
+ headers: { "content-type": "text/plain; charset=utf-8" }
177
+ });
178
+ }
179
+ function reportError(onError, error) {
180
+ try {
181
+ if (onError) onError(error);
182
+ else console.error("[kassza] Az adatkapcsolati üzenet feldolgozása nem sikerült.", error);
183
+ } catch {
184
+ return;
185
+ }
186
+ }
187
+ function acknowledgementOf(value) {
188
+ if (value === void 0 || value === null) return {};
189
+ if (typeof value !== "object") throw new TypeError("Az onPush csak DataLinkAcknowledgement objektumot (registrationNumber, keyError) vagy semmit adhat vissza.");
190
+ return value;
191
+ }
192
+ function configuredKeys(keys) {
193
+ if (keys === void 0) return void 0;
194
+ const trimmed = keys.map((key) => typeof key === "string" ? key.trim() : "");
195
+ if (trimmed.length === 0 || trimmed.some((key) => key === "")) throw new TypeError("A keys lista nem lehet üres, és nem tartalmazhat üres kulcsot.");
196
+ return trimmed;
197
+ }
198
+ async function checkKey(options, keys, push) {
199
+ const key = push.key;
200
+ if (key === void 0) return "KEY_ERR";
201
+ if (keys !== void 0 && !keys.some((candidate) => require_crypto.timingSafeEqual(candidate, key))) return "KEY_ERR";
202
+ if (!options.verifyKey) return true;
203
+ const result = await options.verifyKey(key, push);
204
+ return result === false ? "KEY_ERR" : result;
205
+ }
206
+ function dataLinkHandler(options) {
207
+ if (typeof options.onPush !== "function") throw new TypeError("Add meg az onPush függvényt.");
208
+ const keys = configuredKeys(options.keys);
209
+ if (keys === void 0 && typeof options.verifyKey !== "function") throw new TypeError("Add meg az elfogadott azonosító kulcsokat (keys) vagy a verifyKey függvényt: az adatkapcsolati üzenetnek nincs aláírása, csak a kulcs azonosítja a küldőt.");
210
+ const maxBytes = options.maxBodyBytes ?? 67108864;
211
+ return async (request) => {
212
+ try {
213
+ const push = parseDataLinkPush(await require_request_body.readRequestText(request, maxBytes, () => new DataLinkError("payload_too_large", `Az adatkapcsolati üzenet nagyobb a megengedett ${maxBytes} bájtnál.`)), request.headers.get("x-szamlazzhu-key") ?? void 0);
214
+ const keyCheck = await checkKey(options, keys, push);
215
+ if (keyCheck !== true) return dataLinkResponse(push, { keyError: keyCheck });
216
+ return dataLinkResponse(push, acknowledgementOf(await options.onPush(push)));
217
+ } catch (error) {
218
+ if (error instanceof DataLinkError) return plain(400, error.message);
219
+ reportError(options.onError, error);
220
+ return plain(500, "Az adatkapcsolati üzenet feldolgozása nem sikerült.");
221
+ }
222
+ };
223
+ }
224
+ //#endregion
225
+ exports.DATA_LINK_KEY_HEADER = DATA_LINK_KEY_HEADER;
226
+ exports.DATA_LINK_RESPONSE_ROOTS = DATA_LINK_RESPONSE_ROOTS;
227
+ exports.DEFAULT_DATA_LINK_MAX_BYTES = DEFAULT_DATA_LINK_MAX_BYTES;
228
+ exports.DataLinkError = DataLinkError;
229
+ exports.dataLinkHandler = dataLinkHandler;
230
+ exports.dataLinkResponse = dataLinkResponse;
231
+ exports.dataLinkResponseXml = dataLinkResponseXml;
232
+ exports.parseDataLinkPush = parseDataLinkPush;
@@ -0,0 +1,29 @@
1
+ import { a as DataLinkError, c as DataLinkPush, d as parseDataLinkPush, i as DataLinkBankTransactionPush, l as DataLinkPushKind, n as DataLinkBankTransaction, o as DataLinkErrorReason, r as DataLinkBankTransactionPartner, s as DataLinkInvoicePush, t as DataLinkArchivedReceipt, u as DataLinkReceiptsPush } from "../push-D4nNbCNV.cjs";
2
+ //#region src/data-link/response.d.ts
3
+ type DataLinkKeyError = "KEY_ERR" | "KEY_DEL";
4
+ interface DataLinkAcknowledgement {
5
+ readonly registrationNumber?: string | undefined;
6
+ readonly keyError?: DataLinkKeyError | undefined;
7
+ }
8
+ export declare const DATA_LINK_RESPONSE_ROOTS: Readonly<Record<DataLinkPushKind, {
9
+ readonly root: string;
10
+ readonly namespace: string;
11
+ }>>;
12
+ export declare function dataLinkResponseXml(push: DataLinkPush, acknowledgement?: DataLinkAcknowledgement): string;
13
+ export declare function dataLinkResponse(push: DataLinkPush, acknowledgement?: DataLinkAcknowledgement): Response;
14
+ //#endregion
15
+ //#region src/data-link/handler.d.ts
16
+ export declare const DATA_LINK_KEY_HEADER = "x-szamlazzhu-key";
17
+ export declare const DEFAULT_DATA_LINK_MAX_BYTES = 67108864;
18
+ type DataLinkKeyCheck = boolean | DataLinkKeyError;
19
+ interface DataLinkHandlerOptions {
20
+ readonly keys?: readonly string[] | undefined;
21
+ readonly verifyKey?: ((key: string, push: DataLinkPush) => DataLinkKeyCheck | Promise<DataLinkKeyCheck>) | undefined;
22
+ readonly onPush: (push: DataLinkPush) => unknown;
23
+ readonly onError?: ((error: unknown) => void) | undefined;
24
+ readonly maxBodyBytes?: number | undefined;
25
+ }
26
+ type DataLinkHandler = (request: Request) => Promise<Response>;
27
+ export declare function dataLinkHandler(options: DataLinkHandlerOptions): DataLinkHandler;
28
+ //#endregion
29
+ export { type DataLinkAcknowledgement, type DataLinkArchivedReceipt, type DataLinkBankTransaction, type DataLinkBankTransactionPartner, type DataLinkBankTransactionPush, DataLinkError, type DataLinkErrorReason, type DataLinkHandler, type DataLinkHandlerOptions, type DataLinkInvoicePush, type DataLinkKeyCheck, type DataLinkKeyError, type DataLinkPush, type DataLinkPushKind, type DataLinkReceiptsPush, parseDataLinkPush };
@@ -0,0 +1,29 @@
1
+ import { a as DataLinkError, c as DataLinkPush, d as parseDataLinkPush, i as DataLinkBankTransactionPush, l as DataLinkPushKind, n as DataLinkBankTransaction, o as DataLinkErrorReason, r as DataLinkBankTransactionPartner, s as DataLinkInvoicePush, t as DataLinkArchivedReceipt, u as DataLinkReceiptsPush } from "../push-BXj0Sf0Z.js";
2
+ //#region src/data-link/response.d.ts
3
+ type DataLinkKeyError = "KEY_ERR" | "KEY_DEL";
4
+ interface DataLinkAcknowledgement {
5
+ readonly registrationNumber?: string | undefined;
6
+ readonly keyError?: DataLinkKeyError | undefined;
7
+ }
8
+ export declare const DATA_LINK_RESPONSE_ROOTS: Readonly<Record<DataLinkPushKind, {
9
+ readonly root: string;
10
+ readonly namespace: string;
11
+ }>>;
12
+ export declare function dataLinkResponseXml(push: DataLinkPush, acknowledgement?: DataLinkAcknowledgement): string;
13
+ export declare function dataLinkResponse(push: DataLinkPush, acknowledgement?: DataLinkAcknowledgement): Response;
14
+ //#endregion
15
+ //#region src/data-link/handler.d.ts
16
+ export declare const DATA_LINK_KEY_HEADER = "x-szamlazzhu-key";
17
+ export declare const DEFAULT_DATA_LINK_MAX_BYTES = 67108864;
18
+ type DataLinkKeyCheck = boolean | DataLinkKeyError;
19
+ interface DataLinkHandlerOptions {
20
+ readonly keys?: readonly string[] | undefined;
21
+ readonly verifyKey?: ((key: string, push: DataLinkPush) => DataLinkKeyCheck | Promise<DataLinkKeyCheck>) | undefined;
22
+ readonly onPush: (push: DataLinkPush) => unknown;
23
+ readonly onError?: ((error: unknown) => void) | undefined;
24
+ readonly maxBodyBytes?: number | undefined;
25
+ }
26
+ type DataLinkHandler = (request: Request) => Promise<Response>;
27
+ export declare function dataLinkHandler(options: DataLinkHandlerOptions): DataLinkHandler;
28
+ //#endregion
29
+ export { type DataLinkAcknowledgement, type DataLinkArchivedReceipt, type DataLinkBankTransaction, type DataLinkBankTransactionPartner, type DataLinkBankTransactionPush, DataLinkError, type DataLinkErrorReason, type DataLinkHandler, type DataLinkHandlerOptions, type DataLinkInvoicePush, type DataLinkKeyCheck, type DataLinkKeyError, type DataLinkPush, type DataLinkPushKind, type DataLinkReceiptsPush, parseDataLinkPush };