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,454 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("../errors-EE96_6D_.cjs");
3
+ const require_once = require("../once-BN_3B5OF.cjs");
4
+ const require_dates = require("../dates-CPgBodkP.cjs");
5
+ //#region src/journal/dates.ts
6
+ const MAX_JOURNAL_RANGE_DAYS = 366;
7
+ const DAY_IN_MS = 864e5;
8
+ function invalid(message) {
9
+ return new require_errors.SzamlazzError(message, { category: "validation" });
10
+ }
11
+ function parseDay(value, field) {
12
+ try {
13
+ return require_dates.toAgentDate(value);
14
+ } catch {
15
+ throw invalid(`A napló ${field} dátuma YYYY-MM-DD formájú legyen, kapott: ${value}`);
16
+ }
17
+ }
18
+ function dayNumber(day) {
19
+ return Date.parse(`${day}T00:00:00Z`) / DAY_IN_MS;
20
+ }
21
+ function normalizeRange(range) {
22
+ const from = parseDay(range.from, "from");
23
+ const to = parseDay(range.to, "to");
24
+ const span = dayNumber(to) - dayNumber(from) + 1;
25
+ if (span < 1) throw invalid(`A napló időszakának kezdete (${from}) később van, mint a vége (${to}).`);
26
+ if (span > 366) throw invalid(`A napló egyszerre legfeljebb 366 napot kérdez le, kapott: ${span} nap.`);
27
+ return {
28
+ from,
29
+ to
30
+ };
31
+ }
32
+ function daysOf(range) {
33
+ const { from, to } = normalizeRange(range);
34
+ const days = [];
35
+ const last = dayNumber(to);
36
+ for (let day = dayNumber(from); day <= last; day++) days.push((/* @__PURE__ */ new Date(day * DAY_IN_MS)).toISOString().slice(0, 10));
37
+ return days;
38
+ }
39
+ function inRange(day, range) {
40
+ return day >= range.from && day <= range.to;
41
+ }
42
+ function recentRange(now, days) {
43
+ return {
44
+ from: require_dates.addBudapestDays(now, -(days - 1)),
45
+ to: require_dates.toAgentDate(now)
46
+ };
47
+ }
48
+ //#endregion
49
+ //#region src/journal/entries.ts
50
+ function withoutPdf(receipt) {
51
+ if (receipt.pdf === void 0) return receipt;
52
+ const { pdf: _pdf, ...rest } = receipt;
53
+ return rest;
54
+ }
55
+ function compact(value) {
56
+ return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== void 0));
57
+ }
58
+ function inputDate(value, fallback) {
59
+ if (value instanceof Date || typeof value === "string") try {
60
+ return require_dates.toAgentDate(value);
61
+ } catch {
62
+ return fallback;
63
+ }
64
+ return fallback;
65
+ }
66
+ function receiptEntry(receipt, source, now) {
67
+ const reversal = receipt.type === "reversal";
68
+ return compact({
69
+ kind: "receipt",
70
+ type: reversal ? "reversal" : "document",
71
+ number: receipt.number,
72
+ date: inputDate(receipt.issueDate, require_dates.toAgentDate(now)),
73
+ recordedAt: require_dates.toBudapestTimestamp(now),
74
+ source,
75
+ orderNumber: receipt.orderNumber,
76
+ reversedNumber: reversal ? receipt.reversedReceiptNumber : void 0,
77
+ netTotal: receipt.totals.netAmount,
78
+ grossTotal: receipt.totals.grossAmount,
79
+ currency: receipt.currency,
80
+ isTest: receipt.isTest,
81
+ receipt: withoutPdf(receipt)
82
+ });
83
+ }
84
+ function invoiceDetailsEntry(details, source, now) {
85
+ const reversal = details.header.type === "reversal";
86
+ return compact({
87
+ kind: "invoice",
88
+ type: reversal ? "reversal" : "document",
89
+ number: details.header.number,
90
+ date: inputDate(details.header.issueDate, require_dates.toAgentDate(now)),
91
+ recordedAt: require_dates.toBudapestTimestamp(now),
92
+ source,
93
+ orderNumber: details.header.orderNumber,
94
+ reversedNumber: reversal ? details.header.referencedInvoiceNumber : void 0,
95
+ netTotal: details.totals.netAmount,
96
+ grossTotal: details.totals.grossAmount,
97
+ currency: details.header.currency,
98
+ isTest: details.header.test
99
+ });
100
+ }
101
+ function invoiceResultEntry(result, orderNumber, source, now) {
102
+ if (result.details) return invoiceDetailsEntry(result.details, source, now);
103
+ return compact({
104
+ kind: "invoice",
105
+ type: "document",
106
+ number: result.number,
107
+ date: require_dates.toAgentDate(now),
108
+ recordedAt: require_dates.toBudapestTimestamp(now),
109
+ source,
110
+ orderNumber,
111
+ netTotal: result.invoice?.netTotal,
112
+ grossTotal: result.invoice?.grossTotal
113
+ });
114
+ }
115
+ function eventEntry(event, now) {
116
+ const today = require_dates.toAgentDate(now);
117
+ const recordedAt = require_dates.toBudapestTimestamp(now);
118
+ if (event.kind === "receipt") return receiptEntry(event.document, "hook", now);
119
+ if (event.action === "payment") return void 0;
120
+ if (event.action === "created") return compact({
121
+ kind: "invoice",
122
+ type: "document",
123
+ number: event.number,
124
+ date: inputDate(event.input.issueDate, today),
125
+ recordedAt,
126
+ source: "hook",
127
+ orderNumber: event.input.orderNumber?.trim() || void 0,
128
+ netTotal: event.document.netTotal,
129
+ grossTotal: event.document.grossTotal,
130
+ currency: event.input.currency
131
+ });
132
+ return compact({
133
+ kind: "invoice",
134
+ type: "reversal",
135
+ number: event.number,
136
+ date: today,
137
+ recordedAt,
138
+ source: "hook",
139
+ reversedNumber: event.reversedNumber,
140
+ netTotal: event.document.netTotal,
141
+ grossTotal: event.document.grossTotal
142
+ });
143
+ }
144
+ //#endregion
145
+ //#region src/journal/journal.ts
146
+ const DEFAULT_PENDING_DAYS = 30;
147
+ var JournalWriteError = class extends Error {
148
+ name = "JournalWriteError";
149
+ result;
150
+ orderNumber;
151
+ constructor(orderNumber, result, cause) {
152
+ super(`A(z) ${orderNumber} rendelés bizonylata elkészült, de a naplóba írás nem sikerült. A tétel befejezetlenként a naplóban maradt: a journal.settle() később pótolja. Ne állítsd ki újra a bizonylatot.`, { cause });
153
+ this.orderNumber = orderNumber;
154
+ this.result = result;
155
+ }
156
+ };
157
+ function requireOrderNumber(orderNumber) {
158
+ const trimmed = orderNumber?.trim();
159
+ if (!trimmed) throw new require_errors.SzamlazzError("A naplóhoz add meg a rendelésszámot (orderNumber).", { category: "validation" });
160
+ return trimmed;
161
+ }
162
+ const UNSETTLED_CATEGORIES = /* @__PURE__ */ new Set(["in_progress", "store_unavailable"]);
163
+ function isDefinitelyNotCreated(error) {
164
+ if (!(error instanceof require_errors.SzamlazzError)) return false;
165
+ return !require_once.isUncertainOutcome(error) && !UNSETTLED_CATEGORIES.has(error.category) && error.details?.outcome !== "unknown";
166
+ }
167
+ function archivedReceipt(item) {
168
+ return "receipt" in item && typeof item.receipt === "object" ? item.receipt : item;
169
+ }
170
+ function archiveRange(receipts) {
171
+ const dates = receipts.map((receipt) => receipt.issueDate).filter((date) => /^\d{4}-\d{2}-\d{2}$/.test(date));
172
+ if (dates.length === 0) return void 0;
173
+ const sorted = [...dates].sort();
174
+ return {
175
+ from: sorted[0],
176
+ to: sorted[sorted.length - 1]
177
+ };
178
+ }
179
+ function createJournal(storage, options = {}) {
180
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
181
+ const put = (entry) => entry ? storage.putEntry(entry) : Promise.resolve(false);
182
+ async function reserve(kind, orderNumber) {
183
+ const current = now();
184
+ return storage.putReservation({
185
+ kind,
186
+ orderNumber: requireOrderNumber(orderNumber),
187
+ date: require_dates.toAgentDate(current),
188
+ reservedAt: require_dates.toBudapestTimestamp(current)
189
+ });
190
+ }
191
+ async function release(kind, orderNumber) {
192
+ await storage.deleteReservation(kind, requireOrderNumber(orderNumber));
193
+ }
194
+ async function track(kind, orderNumber, run, entryOf) {
195
+ const order = requireOrderNumber(orderNumber);
196
+ const ownsReservation = await reserve(kind, order);
197
+ let result;
198
+ try {
199
+ result = await run();
200
+ } catch (error) {
201
+ if (ownsReservation && isDefinitelyNotCreated(error)) await storage.deleteReservation(kind, order);
202
+ throw error;
203
+ }
204
+ try {
205
+ await storage.putEntry(entryOf(result));
206
+ await storage.deleteReservation(kind, order);
207
+ } catch (error) {
208
+ throw new JournalWriteError(order, result, error);
209
+ }
210
+ return result;
211
+ }
212
+ async function settleOne(api, reservation) {
213
+ if (reservation.kind === "receipt") {
214
+ if (!api.receipts) throw new TypeError("A nyugták rendezéséhez add meg a receipts API-t.");
215
+ const receipt = await api.receipts.find({
216
+ orderNumber: reservation.orderNumber,
217
+ downloadPdf: false
218
+ });
219
+ if (!receipt) return "notFound";
220
+ await storage.putEntry(receiptEntry(receipt, "settle", now()));
221
+ return "recorded";
222
+ }
223
+ if (!api.invoices) throw new TypeError("A számlák rendezéséhez add meg az invoices API-t.");
224
+ const details = await api.invoices.find({ orderNumber: reservation.orderNumber });
225
+ if (!details) return "notFound";
226
+ await storage.putEntry(invoiceDetailsEntry(details, "settle", now()));
227
+ return "recorded";
228
+ }
229
+ const journal = {
230
+ storage,
231
+ async record(event) {
232
+ await put(eventEntry(event, now()));
233
+ },
234
+ recordReceipt: (receipt) => storage.putEntry(receiptEntry(receipt, "manual", now())),
235
+ recordInvoice: (details) => storage.putEntry(invoiceDetailsEntry(details, "manual", now())),
236
+ reserve,
237
+ release,
238
+ trackReceipt: (orderNumber, run) => track("receipt", orderNumber, run, (result) => receiptEntry("receipt" in result ? result.receipt : result, "track", now())),
239
+ trackInvoice: (orderNumber, run) => track("invoice", orderNumber, run, (result) => invoiceResultEntry(result, requireOrderNumber(orderNumber), "track", now())),
240
+ async entries(query) {
241
+ return (await storage.listEntries(normalizeRange(query))).filter((entry) => query.kind === void 0 || entry.kind === query.kind).sort((a, b) => a.date.localeCompare(b.date) || a.number.localeCompare(b.number, "hu"));
242
+ },
243
+ async receipts(query) {
244
+ return (await journal.entries({
245
+ ...query,
246
+ kind: "receipt"
247
+ })).map((entry) => entry.receipt).filter((receipt) => receipt !== void 0).filter((receipt) => query.includeTest === true || !receipt.isTest);
248
+ },
249
+ async pending(range) {
250
+ return storage.listReservations(range ?? recentRange(now(), 30));
251
+ },
252
+ async settle(api, settleOptions = {}) {
253
+ const reservations = await journal.pending(settleOptions.range);
254
+ const recorded = [];
255
+ const notFound = [];
256
+ const failed = [];
257
+ for (const reservation of reservations) try {
258
+ const outcome = await settleOne(api, reservation);
259
+ if (outcome === "recorded" || settleOptions.releaseNotFound === true) await storage.deleteReservation(reservation.kind, reservation.orderNumber);
260
+ if (outcome === "recorded") recorded.push(reservation);
261
+ else notFound.push(reservation);
262
+ } catch (error) {
263
+ failed.push({
264
+ reservation,
265
+ error
266
+ });
267
+ }
268
+ return {
269
+ recorded,
270
+ notFound,
271
+ failed
272
+ };
273
+ },
274
+ async reconcile(archive, reconcileOptions = {}) {
275
+ const receipts = archive.map(archivedReceipt);
276
+ const derived = archiveRange(receipts);
277
+ const range = reconcileOptions.from !== void 0 || reconcileOptions.to !== void 0 ? normalizeRange({
278
+ from: reconcileOptions.from ?? derived?.from ?? reconcileOptions.to ?? "",
279
+ to: reconcileOptions.to ?? derived?.to ?? reconcileOptions.from ?? ""
280
+ }) : derived;
281
+ const journaled = range ? await journal.entries({
282
+ ...range,
283
+ kind: "receipt"
284
+ }) : [];
285
+ const known = new Set(journaled.map((entry) => entry.number));
286
+ const archived = /* @__PURE__ */ new Set();
287
+ const added = [];
288
+ for (const receipt of receipts) {
289
+ if (archived.has(receipt.number)) continue;
290
+ archived.add(receipt.number);
291
+ if (range && !inRange(receipt.issueDate, range)) continue;
292
+ if (known.has(receipt.number)) continue;
293
+ if (reconcileOptions.dryRun !== true) await storage.putEntry(receiptEntry(receipt, "reconcile", now()));
294
+ added.push(receipt.number);
295
+ }
296
+ const missingFromArchive = journaled.map((entry) => entry.number).filter((number) => !archived.has(number));
297
+ return {
298
+ range,
299
+ added,
300
+ missingFromArchive,
301
+ matched: journaled.length - missingFromArchive.length
302
+ };
303
+ }
304
+ };
305
+ return journal;
306
+ }
307
+ //#endregion
308
+ //#region src/journal/storage.ts
309
+ const JOURNAL_KEY_PREFIX = "szamlazz:journal:";
310
+ const DEFAULT_JOURNAL_RETENTION_DAYS = 400;
311
+ const DEFAULT_RESERVATION_TTL_DAYS = 30;
312
+ const DAY_IN_SECONDS = 86400;
313
+ const READ_BATCH = 50;
314
+ function configurationError(message) {
315
+ return new require_errors.SzamlazzError(message, { category: "configuration" });
316
+ }
317
+ function positiveDays(value, fallback, field) {
318
+ if (value === void 0) return fallback;
319
+ if (!Number.isFinite(value) || value < 1) throw configurationError(`A(z) ${field} legalább 1 nap legyen, kapott: ${String(value)}`);
320
+ return Math.ceil(value);
321
+ }
322
+ function parseJson(value, guard) {
323
+ if (typeof value !== "string" || value === "") return void 0;
324
+ try {
325
+ const parsed = JSON.parse(value);
326
+ return guard(parsed) ? parsed : void 0;
327
+ } catch {
328
+ return;
329
+ }
330
+ }
331
+ function isEntry(value) {
332
+ if (typeof value !== "object" || value === null) return false;
333
+ const entry = value;
334
+ return (entry.kind === "invoice" || entry.kind === "receipt") && typeof entry.number === "string" && typeof entry.date === "string";
335
+ }
336
+ function isReservation(value) {
337
+ if (typeof value !== "object" || value === null) return false;
338
+ const reservation = value;
339
+ return (reservation.kind === "invoice" || reservation.kind === "receipt") && typeof reservation.orderNumber === "string" && typeof reservation.date === "string";
340
+ }
341
+ function slotTarget(value) {
342
+ if (typeof value !== "string") return void 0;
343
+ const separator = value.indexOf(":");
344
+ if (separator <= 0) return void 0;
345
+ const kind = value.slice(0, separator);
346
+ if (kind !== "invoice" && kind !== "receipt") return void 0;
347
+ return [kind, value.slice(separator + 1)];
348
+ }
349
+ async function inBatches(items, run) {
350
+ const results = [];
351
+ for (let index = 0; index < items.length; index += READ_BATCH) results.push(...await Promise.all(items.slice(index, index + READ_BATCH).map(run)));
352
+ return results;
353
+ }
354
+ function kvJournal(store, options = {}) {
355
+ const increment = store.increment?.bind(store);
356
+ if (!increment) throw configurationError("A naplóhoz olyan tároló kell, amely atomikusan tud számlálót növelni (increment), különben párhuzamos írásnál bejegyzés veszhet el. Használd a kassza/stores Redis, Upstash vagy Durable Object tárolóját. A Cloudflare KV erre nem alkalmas.");
357
+ const prefix = options.prefix ?? "szamlazz:journal:";
358
+ const retention = positiveDays(options.retentionDays, 400, "retentionDays") * DAY_IN_SECONDS;
359
+ const reservationTtl = positiveDays(options.reservationTtlDays, 30, "reservationTtlDays") * DAY_IN_SECONDS;
360
+ const entryKey = (kind, number) => `${prefix}entry:${kind}:${number}`;
361
+ const reservationKey = (kind, orderNumber) => `${prefix}reservation:${kind}:${orderNumber}`;
362
+ async function appendToDay(index, day, target, ttl) {
363
+ const slot = await increment?.(`${prefix}${index}:${day}:count`, ttl);
364
+ await store.set(`${prefix}${index}:${day}:${slot}`, target, ttl);
365
+ }
366
+ async function slotsOf(index, range) {
367
+ const targets = [];
368
+ for (const day of daysOf(range)) {
369
+ const count = Number.parseInt(await store.get(`${prefix}${index}:${day}:count`) ?? "0", 10);
370
+ if (!Number.isInteger(count) || count < 1) continue;
371
+ const slots = Array.from({ length: count }, (_, slot) => `${prefix}${index}:${day}:${slot + 1}`);
372
+ for (const value of await inBatches(slots, async (key) => store.get(key))) if (typeof value === "string") targets.push(value);
373
+ }
374
+ return [...new Set(targets)];
375
+ }
376
+ return {
377
+ async getEntry(kind, number) {
378
+ return parseJson(await store.get(entryKey(kind, number)), isEntry);
379
+ },
380
+ async putEntry(entry) {
381
+ const key = entryKey(entry.kind, entry.number);
382
+ const existing = await store.get(key);
383
+ if (existing !== void 0 && existing !== null) return false;
384
+ await appendToDay("day", entry.date, `${entry.kind}:${entry.number}`, retention);
385
+ const value = JSON.stringify(entry);
386
+ if (store.setIfAbsent) return store.setIfAbsent(key, value, retention);
387
+ await store.set(key, value, retention);
388
+ return true;
389
+ },
390
+ async listEntries(range) {
391
+ const normalized = normalizeRange(range);
392
+ return (await inBatches((await slotsOf("day", normalized)).map(slotTarget).filter((t) => t !== void 0), async ([kind, number]) => parseJson(await store.get(entryKey(kind, number)), isEntry))).filter((entry) => entry !== void 0 && inRange(entry.date, normalized));
393
+ },
394
+ async putReservation(reservation) {
395
+ const key = reservationKey(reservation.kind, reservation.orderNumber);
396
+ const value = JSON.stringify(reservation);
397
+ await appendToDay("rday", reservation.date, `${reservation.kind}:${reservation.orderNumber}`, reservationTtl);
398
+ if (store.setIfAbsent) return store.setIfAbsent(key, value, reservationTtl);
399
+ const existing = await store.get(key);
400
+ if (existing !== void 0 && existing !== null) return false;
401
+ await store.set(key, value, reservationTtl);
402
+ return true;
403
+ },
404
+ async deleteReservation(kind, orderNumber) {
405
+ await store.delete(reservationKey(kind, orderNumber));
406
+ },
407
+ async listReservations(range) {
408
+ return (await inBatches((await slotsOf("rday", normalizeRange(range))).map(slotTarget).filter((t) => t !== void 0), async ([kind, orderNumber]) => parseJson(await store.get(reservationKey(kind, orderNumber)), isReservation))).filter((reservation) => reservation !== void 0);
409
+ }
410
+ };
411
+ }
412
+ function memoryJournal() {
413
+ const entries = /* @__PURE__ */ new Map();
414
+ const reservations = /* @__PURE__ */ new Map();
415
+ const key = (kind, id) => `${kind}:${id}`;
416
+ return {
417
+ async getEntry(kind, number) {
418
+ return entries.get(key(kind, number));
419
+ },
420
+ async putEntry(entry) {
421
+ const id = key(entry.kind, entry.number);
422
+ if (entries.has(id)) return false;
423
+ entries.set(id, entry);
424
+ return true;
425
+ },
426
+ async listEntries(range) {
427
+ const normalized = normalizeRange(range);
428
+ return [...entries.values()].filter((entry) => inRange(entry.date, normalized));
429
+ },
430
+ async putReservation(reservation) {
431
+ const id = key(reservation.kind, reservation.orderNumber);
432
+ if (reservations.has(id)) return false;
433
+ reservations.set(id, reservation);
434
+ return true;
435
+ },
436
+ async deleteReservation(kind, orderNumber) {
437
+ reservations.delete(key(kind, orderNumber));
438
+ },
439
+ async listReservations(range) {
440
+ const normalized = normalizeRange(range);
441
+ return [...reservations.values()].filter((reservation) => inRange(reservation.date, normalized));
442
+ }
443
+ };
444
+ }
445
+ //#endregion
446
+ exports.DEFAULT_JOURNAL_RETENTION_DAYS = DEFAULT_JOURNAL_RETENTION_DAYS;
447
+ exports.DEFAULT_PENDING_DAYS = DEFAULT_PENDING_DAYS;
448
+ exports.DEFAULT_RESERVATION_TTL_DAYS = DEFAULT_RESERVATION_TTL_DAYS;
449
+ exports.JOURNAL_KEY_PREFIX = JOURNAL_KEY_PREFIX;
450
+ exports.JournalWriteError = JournalWriteError;
451
+ exports.MAX_JOURNAL_RANGE_DAYS = MAX_JOURNAL_RANGE_DAYS;
452
+ exports.createJournal = createJournal;
453
+ exports.kvJournal = kvJournal;
454
+ exports.memoryJournal = memoryJournal;
@@ -0,0 +1,18 @@
1
+ import { n as KeyValueStore } from "../store-C1rHd9DB.cjs";
2
+ import { _ as JournalRange, a as JournalReceiptQuery, c as JournalSettleApi, d as JournalWriteError, f as createJournal, g as JournalEntryType, h as JournalEntrySource, i as JournalOptions, l as JournalSettleOptions, m as JournalEntry, n as Journal, o as JournalReconcileOptions, p as JournalDocumentKind, r as JournalEntryQuery, s as JournalReconciliation, t as DEFAULT_PENDING_DAYS, u as JournalSettlement, v as JournalReservation, y as JournalStorage } from "../journal-DvI81Kt7.cjs";
3
+ //#region src/journal/dates.d.ts
4
+ export declare const MAX_JOURNAL_RANGE_DAYS = 366;
5
+ //#endregion
6
+ //#region src/journal/storage.d.ts
7
+ export declare const JOURNAL_KEY_PREFIX = "szamlazz:journal:";
8
+ export declare const DEFAULT_JOURNAL_RETENTION_DAYS = 400;
9
+ export declare const DEFAULT_RESERVATION_TTL_DAYS = 30;
10
+ interface KvJournalOptions {
11
+ readonly prefix?: string | undefined;
12
+ readonly retentionDays?: number | undefined;
13
+ readonly reservationTtlDays?: number | undefined;
14
+ }
15
+ export declare function kvJournal(store: KeyValueStore, options?: KvJournalOptions): JournalStorage;
16
+ export declare function memoryJournal(): JournalStorage;
17
+ //#endregion
18
+ export { DEFAULT_PENDING_DAYS, type Journal, type JournalDocumentKind, type JournalEntry, type JournalEntryQuery, type JournalEntrySource, type JournalEntryType, type JournalOptions, type JournalRange, type JournalReceiptQuery, type JournalReconcileOptions, type JournalReconciliation, type JournalReservation, type JournalSettleApi, type JournalSettleOptions, type JournalSettlement, type JournalStorage, JournalWriteError, type KvJournalOptions, createJournal };
@@ -0,0 +1,18 @@
1
+ import { n as KeyValueStore } from "../store-C1rHd9DB.js";
2
+ import { _ as JournalRange, a as JournalReceiptQuery, c as JournalSettleApi, d as JournalWriteError, f as createJournal, g as JournalEntryType, h as JournalEntrySource, i as JournalOptions, l as JournalSettleOptions, m as JournalEntry, n as Journal, o as JournalReconcileOptions, p as JournalDocumentKind, r as JournalEntryQuery, s as JournalReconciliation, t as DEFAULT_PENDING_DAYS, u as JournalSettlement, v as JournalReservation, y as JournalStorage } from "../journal-Y9qrIB8G.js";
3
+ //#region src/journal/dates.d.ts
4
+ export declare const MAX_JOURNAL_RANGE_DAYS = 366;
5
+ //#endregion
6
+ //#region src/journal/storage.d.ts
7
+ export declare const JOURNAL_KEY_PREFIX = "szamlazz:journal:";
8
+ export declare const DEFAULT_JOURNAL_RETENTION_DAYS = 400;
9
+ export declare const DEFAULT_RESERVATION_TTL_DAYS = 30;
10
+ interface KvJournalOptions {
11
+ readonly prefix?: string | undefined;
12
+ readonly retentionDays?: number | undefined;
13
+ readonly reservationTtlDays?: number | undefined;
14
+ }
15
+ export declare function kvJournal(store: KeyValueStore, options?: KvJournalOptions): JournalStorage;
16
+ export declare function memoryJournal(): JournalStorage;
17
+ //#endregion
18
+ export { DEFAULT_PENDING_DAYS, type Journal, type JournalDocumentKind, type JournalEntry, type JournalEntryQuery, type JournalEntrySource, type JournalEntryType, type JournalOptions, type JournalRange, type JournalReceiptQuery, type JournalReconcileOptions, type JournalReconciliation, type JournalReservation, type JournalSettleApi, type JournalSettleOptions, type JournalSettlement, type JournalStorage, JournalWriteError, type KvJournalOptions, createJournal };