kassza 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/agents/README.md +59 -0
  4. package/agents/api.md +206 -0
  5. package/agents/pitfalls.md +52 -0
  6. package/agents/recipes.md +217 -0
  7. package/agents/skills/kassza/SKILL.md +29 -0
  8. package/assets/logo-wordmark.svg +25 -0
  9. package/assets/logo.svg +19 -0
  10. package/dist/binary-B89HM03_.cjs +63 -0
  11. package/dist/binary-D0M9U2MD.js +34 -0
  12. package/dist/client-B9kbKKBf.d.cts +748 -0
  13. package/dist/client-zv4enyq7.d.ts +748 -0
  14. package/dist/cookie-stores/index.cjs +153 -0
  15. package/dist/cookie-stores/index.d.cts +63 -0
  16. package/dist/cookie-stores/index.d.ts +63 -0
  17. package/dist/cookie-stores/index.js +144 -0
  18. package/dist/create-BZd6CUO7.cjs +1160 -0
  19. package/dist/create-DDZaNlOz.js +939 -0
  20. package/dist/dates-D2XebOIg.js +34 -0
  21. package/dist/dates-DtHzwNU6.d.cts +7 -0
  22. package/dist/dates-DtHzwNU6.d.ts +7 -0
  23. package/dist/dates-PPxH0n5H.cjs +57 -0
  24. package/dist/errors-B0QJhUW1.cjs +302 -0
  25. package/dist/errors-DapdV5DK.js +273 -0
  26. package/dist/index-CYAGCdKJ.d.cts +56 -0
  27. package/dist/index-CYAGCdKJ.d.ts +56 -0
  28. package/dist/index.cjs +1406 -0
  29. package/dist/index.d.cts +8 -0
  30. package/dist/index.d.ts +8 -0
  31. package/dist/index.js +1394 -0
  32. package/dist/ipn/index.cjs +108 -0
  33. package/dist/ipn/index.d.cts +32 -0
  34. package/dist/ipn/index.d.ts +32 -0
  35. package/dist/ipn/index.js +101 -0
  36. package/dist/money/index.cjs +15 -0
  37. package/dist/money/index.d.cts +2 -0
  38. package/dist/money/index.d.ts +2 -0
  39. package/dist/money/index.js +2 -0
  40. package/dist/money-C9j7nBNP.js +258 -0
  41. package/dist/money-DkiGukAw.cjs +335 -0
  42. package/dist/session-CRGOuz-R.cjs +100 -0
  43. package/dist/session-Dm_45x8K.d.cts +11 -0
  44. package/dist/session-Dm_45x8K.d.ts +11 -0
  45. package/dist/session-OJMLGufT.js +77 -0
  46. package/dist/shared-CrxlxI8n.cjs +207 -0
  47. package/dist/shared-D6DLa4b7.js +100 -0
  48. package/dist/storage/fs.cjs +88 -0
  49. package/dist/storage/fs.d.cts +13 -0
  50. package/dist/storage/fs.d.ts +13 -0
  51. package/dist/storage/fs.js +87 -0
  52. package/dist/storage/index.cjs +643 -0
  53. package/dist/storage/index.d.cts +288 -0
  54. package/dist/storage/index.d.ts +288 -0
  55. package/dist/storage/index.js +619 -0
  56. package/dist/testing/index.cjs +409 -0
  57. package/dist/testing/index.d.cts +35 -0
  58. package/dist/testing/index.d.ts +35 -0
  59. package/dist/testing/index.js +407 -0
  60. package/dist/types-DVRgwcqg.d.cts +26 -0
  61. package/dist/types-DVRgwcqg.d.ts +26 -0
  62. package/dist/validators/index.cjs +296 -0
  63. package/dist/validators/index.d.cts +51 -0
  64. package/dist/validators/index.d.ts +51 -0
  65. package/dist/validators/index.js +278 -0
  66. package/llms.txt +16 -0
  67. package/package.json +151 -0
@@ -0,0 +1,407 @@
1
+ import { f as resolveInvoice, n as calculateReceiptItems, t as buildCreateReceiptXml } from "../create-DDZaNlOz.js";
2
+ import { n as SzamlazzError } from "../errors-DapdV5DK.js";
3
+ import { n as toAgentDate } from "../dates-D2XebOIg.js";
4
+ import { i as summarizeItems } from "../money-C9j7nBNP.js";
5
+ //#region src/testing/index.ts
6
+ const MOCK_PDF = new TextEncoder().encode("%PDF-1.4\n1 0 obj << /Type /Catalog >> endobj\ntrailer << /Root 1 0 R >>\n%%EOF\n");
7
+ function notFound(code, message) {
8
+ return new SzamlazzError(`[${code}] ${message}`, {
9
+ category: "not_found",
10
+ code
11
+ });
12
+ }
13
+ function invoiceTypeCode(type) {
14
+ return {
15
+ invoice: "SZ",
16
+ proforma: "D",
17
+ advance: "E",
18
+ final: "V",
19
+ corrective: "H",
20
+ deliveryNote: "SZL",
21
+ reversal: "SS"
22
+ }[type];
23
+ }
24
+ function referenceMatches(record, reference) {
25
+ if (typeof reference === "string") return record.number === reference;
26
+ if ("invoiceNumber" in reference) return record.number === reference.invoiceNumber;
27
+ if ("orderNumber" in reference) return record.input?.orderNumber === reference.orderNumber;
28
+ return record.input?.externalId === reference.externalId;
29
+ }
30
+ function normalizePayments(input, today) {
31
+ if ("payments" in input) return [...input.payments];
32
+ return [{
33
+ amount: input.amount,
34
+ method: input.method ?? "átutalás",
35
+ date: input.date ?? today,
36
+ description: input.description
37
+ }];
38
+ }
39
+ function createMockKassza(options = {}) {
40
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
41
+ const calls = [];
42
+ const failures = /* @__PURE__ */ new Map();
43
+ const invoices = /* @__PURE__ */ new Map();
44
+ const receipts = /* @__PURE__ */ new Map();
45
+ const sequences = /* @__PURE__ */ new Map();
46
+ let receiptId = 0;
47
+ const nextNumber = (prefix) => {
48
+ const key = `${prefix}-${toAgentDate(now()).slice(0, 4)}`;
49
+ const next = (sequences.get(key) ?? 0) + 1;
50
+ sequences.set(key, next);
51
+ return `${key}-${next}`;
52
+ };
53
+ const record = (method, args) => {
54
+ calls.push({
55
+ method,
56
+ args
57
+ });
58
+ const failure = failures.get(method);
59
+ if (failure) {
60
+ failures.delete(method);
61
+ throw failure;
62
+ }
63
+ };
64
+ const findInvoice = (reference) => {
65
+ const found = [...invoices.values()].filter((candidate) => !candidate.deleted && referenceMatches(candidate, reference)).at(-1);
66
+ if (!found) throw notFound(7, "Hiányzó adat: ismeretlen számlaszám, rendelésszám vagy külső azonosító.");
67
+ return found;
68
+ };
69
+ const detailsOf = (found, includePdf) => ({
70
+ ...found.details,
71
+ header: {
72
+ ...found.details.header,
73
+ reversed: found.reversed
74
+ },
75
+ payments: [...found.payments],
76
+ ...includePdf ? { pdf: MOCK_PDF } : {}
77
+ });
78
+ const findReceipt = (key) => {
79
+ const entries = [...receipts.values()];
80
+ const found = typeof key === "string" ? receipts.get(key) : entries.findLast((entry) => key.receiptNumber !== void 0 && entry.receipt.number === key.receiptNumber || key.orderNumber !== void 0 && entry.receipt.orderNumber === key.orderNumber);
81
+ if (!found) throw notFound(339, "A nyugtaszám nem létezik.");
82
+ return found;
83
+ };
84
+ const createInvoiceRecord = (input) => {
85
+ const resolved = resolveInvoice(options.defaults?.invoice ?? {}, input, now());
86
+ const items = resolved.items.map((item) => item.amounts);
87
+ const totals = summarizeItems(items);
88
+ const typePrefix = resolved.type === "proforma" ? "D" : "E";
89
+ const number = nextNumber(resolved.prefix ? `${typePrefix}-${resolved.prefix}` : `${typePrefix}-KASSZA`);
90
+ const details = {
91
+ seller: { name: "Kassza Teszt Kft." },
92
+ header: {
93
+ number,
94
+ type: resolved.type,
95
+ typeCode: invoiceTypeCode(resolved.type),
96
+ eInvoice: resolved.eInvoice,
97
+ issueDate: resolved.issueDate,
98
+ fulfillmentDate: resolved.fulfillmentDate,
99
+ dueDate: resolved.dueDate,
100
+ paymentMethod: resolved.paymentMethod,
101
+ orderNumber: input.orderNumber,
102
+ language: resolved.language,
103
+ currency: resolved.currency,
104
+ comment: input.comment,
105
+ test: true
106
+ },
107
+ buyer: {
108
+ name: input.buyer.name,
109
+ email: input.buyer.email,
110
+ taxNumber: input.buyer.taxNumber,
111
+ address: {
112
+ country: input.buyer.country,
113
+ zip: input.buyer.zip,
114
+ city: input.buyer.city,
115
+ address: input.buyer.address
116
+ }
117
+ },
118
+ items: resolved.items.map((item) => ({
119
+ name: item.amounts.name,
120
+ quantity: item.amounts.quantity,
121
+ unit: item.unit,
122
+ netUnitPrice: item.amounts.netUnitPrice,
123
+ vat: typeof item.amounts.vat === "number" ? item.amounts.vat : 0,
124
+ vatCode: typeof item.amounts.vat === "number" ? void 0 : item.amounts.vat,
125
+ netAmount: item.amounts.netAmount,
126
+ vatAmount: item.amounts.vatAmount,
127
+ grossAmount: item.amounts.grossAmount,
128
+ comment: item.input.comment
129
+ })),
130
+ financialItems: [],
131
+ labels: [],
132
+ totals: {
133
+ netAmount: totals.netAmount,
134
+ vatAmount: totals.vatAmount,
135
+ grossAmount: totals.grossAmount,
136
+ byVat: totals.byVat.map((bucket) => ({
137
+ vat: typeof bucket.vat === "number" ? bucket.vat : 0,
138
+ vatCode: typeof bucket.vat === "number" ? void 0 : bucket.vat,
139
+ netAmount: bucket.netAmount,
140
+ vatAmount: bucket.vatAmount,
141
+ grossAmount: bucket.grossAmount
142
+ }))
143
+ },
144
+ payments: []
145
+ };
146
+ const paid = input.paid ? [{
147
+ date: resolved.issueDate,
148
+ method: resolved.paymentMethod,
149
+ amount: totals.grossAmount
150
+ }] : [];
151
+ invoices.set(number, {
152
+ number,
153
+ type: resolved.type,
154
+ input,
155
+ details,
156
+ payments: paid,
157
+ reversed: false,
158
+ deleted: false
159
+ });
160
+ return {
161
+ number,
162
+ netTotal: totals.netAmount,
163
+ grossTotal: totals.grossAmount,
164
+ outstanding: input.paid ? 0 : totals.grossAmount,
165
+ items,
166
+ ...resolved.downloadPdf ? { pdf: MOCK_PDF } : {}
167
+ };
168
+ };
169
+ const createReceiptRecord = (input, callId) => {
170
+ const defaults = options.defaults?.receipt ?? {};
171
+ buildCreateReceiptXml([], defaults, input);
172
+ if (callId !== void 0 && [...receipts.values()].some((entry) => entry.receipt.callId === callId)) throw new SzamlazzError("[338] A hívásazonosító már létezik.", {
173
+ category: "duplicate",
174
+ code: 338
175
+ });
176
+ const currency = input.currency ?? defaults.currency ?? "HUF";
177
+ const calculated = calculateReceiptItems(input.items, currency);
178
+ const totals = summarizeItems(calculated.map((item) => item.amounts));
179
+ const prefix = (input.prefix ?? defaults.prefix ?? "NY").trim();
180
+ const paymentMethod = (input.paymentMethod ?? defaults.paymentMethod ?? "").trim();
181
+ receiptId += 1;
182
+ const receipt = {
183
+ id: receiptId,
184
+ number: nextNumber(prefix),
185
+ callId,
186
+ type: "receipt",
187
+ isReversed: false,
188
+ issueDate: toAgentDate(now()),
189
+ paymentMethod,
190
+ currency,
191
+ comment: input.comment,
192
+ isTest: true,
193
+ orderNumber: input.orderNumber,
194
+ items: calculated.map((item) => ({
195
+ name: item.input.name,
196
+ quantity: item.amounts.quantity,
197
+ unit: item.input.unit ?? defaults.unit ?? "db",
198
+ netUnitPrice: item.amounts.netUnitPrice,
199
+ vat: item.vat,
200
+ vatPercentage: typeof item.vat === "number" ? item.vat : 0,
201
+ netAmount: item.amounts.netAmount,
202
+ vatAmount: item.amounts.vatAmount,
203
+ grossAmount: item.amounts.grossAmount
204
+ })),
205
+ payments: (input.payments ?? []).map((payment) => ({ ...payment })),
206
+ totals: {
207
+ netAmount: totals.netAmount,
208
+ vatAmount: totals.vatAmount,
209
+ grossAmount: totals.grossAmount,
210
+ byVat: totals.byVat.map((bucket) => ({
211
+ vat: bucket.vat,
212
+ vatPercentage: typeof bucket.vat === "number" ? bucket.vat : 0,
213
+ netAmount: bucket.netAmount,
214
+ vatAmount: bucket.vatAmount,
215
+ grossAmount: bucket.grossAmount
216
+ }))
217
+ }
218
+ };
219
+ receipts.set(receipt.number, {
220
+ receipt,
221
+ sentTo: []
222
+ });
223
+ return input.downloadPdf ?? defaults.downloadPdf ?? true ? {
224
+ ...receipt,
225
+ pdf: MOCK_PDF
226
+ } : receipt;
227
+ };
228
+ const run = async (method, args, fn) => {
229
+ record(method, args);
230
+ return fn();
231
+ };
232
+ const nullIfMissing = async (promise) => {
233
+ try {
234
+ return await promise;
235
+ } catch (error) {
236
+ if (error instanceof SzamlazzError && error.isNotFound) return null;
237
+ throw error;
238
+ }
239
+ };
240
+ const getInvoice = (reference, includePdf) => run("invoices.get", [reference], () => detailsOf(findInvoice(reference), includePdf ?? false));
241
+ const getReceipt = (input) => run("receipts.get", [input], () => {
242
+ const found = findReceipt(input);
243
+ return (typeof input === "string" ? true : input.downloadPdf ?? true) ? {
244
+ ...found.receipt,
245
+ pdf: MOCK_PDF
246
+ } : found.receipt;
247
+ });
248
+ return {
249
+ calls,
250
+ invoiceRecords: invoices,
251
+ receiptRecords: receipts,
252
+ failNext(method, error) {
253
+ failures.set(method, error ?? new SzamlazzError("Hálózati hiba a Számlázz.hu elérésekor.", { category: "network" }));
254
+ },
255
+ reset() {
256
+ calls.length = 0;
257
+ failures.clear();
258
+ invoices.clear();
259
+ receipts.clear();
260
+ sequences.clear();
261
+ receiptId = 0;
262
+ },
263
+ invoices: {
264
+ create: (input) => run("invoices.create", [input], () => createInvoiceRecord(input)),
265
+ preview: (input) => run("invoices.preview", [input], () => {
266
+ const items = resolveInvoice(options.defaults?.invoice ?? {}, input, now()).items.map((item) => item.amounts);
267
+ const totals = summarizeItems(items);
268
+ return {
269
+ pdf: MOCK_PDF,
270
+ netTotal: totals.netAmount,
271
+ grossTotal: totals.grossAmount,
272
+ items
273
+ };
274
+ }),
275
+ reverse: (input) => run("invoices.reverse", [input], () => {
276
+ const invoiceNumber = typeof input === "string" ? input : input.invoiceNumber;
277
+ const original = findInvoice(invoiceNumber);
278
+ original.reversed = true;
279
+ const number = nextNumber("E-STORNO");
280
+ const totals = original.details.totals;
281
+ invoices.set(number, {
282
+ number,
283
+ type: "reversal",
284
+ input: void 0,
285
+ details: {
286
+ ...original.details,
287
+ header: {
288
+ ...original.details.header,
289
+ number,
290
+ type: "reversal",
291
+ typeCode: "SS",
292
+ referencedInvoiceNumber: invoiceNumber
293
+ },
294
+ totals: {
295
+ netAmount: -totals.netAmount,
296
+ vatAmount: -totals.vatAmount,
297
+ grossAmount: -totals.grossAmount,
298
+ byVat: []
299
+ }
300
+ },
301
+ payments: [],
302
+ reversed: false,
303
+ deleted: false
304
+ });
305
+ const downloadPdf = typeof input === "string" || (input.downloadPdf ?? true);
306
+ return {
307
+ number,
308
+ netTotal: -totals.netAmount,
309
+ grossTotal: -totals.grossAmount,
310
+ ...downloadPdf ? { pdf: MOCK_PDF } : {}
311
+ };
312
+ }),
313
+ registerPayment: (input) => run("invoices.registerPayment", [input], () => {
314
+ const found = findInvoice(input.invoiceNumber);
315
+ const today = toAgentDate(now());
316
+ const entries = normalizePayments(input, today).map((entry) => ({
317
+ date: toAgentDate(entry.date ?? today),
318
+ method: entry.method,
319
+ amount: entry.amount,
320
+ comment: entry.description
321
+ }));
322
+ found.payments = input.additive === false ? entries : [...found.payments, ...entries];
323
+ const paid = found.payments.reduce((sum, payment) => sum + payment.amount, 0);
324
+ return {
325
+ invoiceNumber: found.number,
326
+ netTotal: found.details.totals.netAmount,
327
+ grossTotal: found.details.totals.grossAmount,
328
+ outstanding: Math.max(0, found.details.totals.grossAmount - paid)
329
+ };
330
+ }),
331
+ clearPayments: (input) => run("invoices.clearPayments", [input], () => {
332
+ const found = findInvoice(typeof input === "string" ? input : input.invoiceNumber);
333
+ found.payments = [];
334
+ return {
335
+ invoiceNumber: found.number,
336
+ netTotal: found.details.totals.netAmount,
337
+ grossTotal: found.details.totals.grossAmount,
338
+ outstanding: found.details.totals.grossAmount
339
+ };
340
+ }),
341
+ getPdf: (reference) => run("invoices.getPdf", [reference], () => {
342
+ const found = findInvoice(reference);
343
+ return {
344
+ pdf: MOCK_PDF,
345
+ number: found.number,
346
+ netTotal: found.details.totals.netAmount,
347
+ grossTotal: found.details.totals.grossAmount
348
+ };
349
+ }),
350
+ get: (reference, query) => getInvoice(reference, query?.includePdf),
351
+ find: (reference, query) => nullIfMissing(getInvoice(reference, query?.includePdf)),
352
+ deleteProforma: (reference) => run("invoices.deleteProforma", [reference], () => {
353
+ const target = typeof reference === "string" ? reference : "proformaNumber" in reference ? reference.proformaNumber : { orderNumber: reference.orderNumber };
354
+ const proforma = [...invoices.values()].filter((candidate) => candidate.type === "proforma" && !candidate.deleted).findLast((candidate) => referenceMatches(candidate, target));
355
+ if (!proforma) throw notFound(335, "A hivatkozott díjbekérő nem található.");
356
+ proforma.deleted = true;
357
+ })
358
+ },
359
+ receipts: {
360
+ create: (input) => run("receipts.create", [input], () => createReceiptRecord(input, input.callId)),
361
+ reverse: (input) => run("receipts.reverse", [input], () => {
362
+ const receiptNumber = typeof input === "string" ? input : input.receiptNumber;
363
+ const original = findReceipt(receiptNumber);
364
+ original.receipt = {
365
+ ...original.receipt,
366
+ isReversed: true
367
+ };
368
+ receiptId += 1;
369
+ const reversal = {
370
+ ...original.receipt,
371
+ id: receiptId,
372
+ number: nextNumber(`${original.receipt.number.split("-")[0] ?? "NY"}-STORNO`),
373
+ type: "reversal",
374
+ isReversed: false,
375
+ reversedReceiptNumber: receiptNumber,
376
+ issueDate: toAgentDate(now())
377
+ };
378
+ receipts.set(reversal.number, {
379
+ receipt: reversal,
380
+ sentTo: []
381
+ });
382
+ return {
383
+ ...reversal,
384
+ pdf: MOCK_PDF
385
+ };
386
+ }),
387
+ get: getReceipt,
388
+ find: (input, requestOptions) => nullIfMissing(getReceipt(input, requestOptions)),
389
+ send: (input) => run("receipts.send", [input], () => {
390
+ const found = findReceipt(input.receiptNumber);
391
+ const emails = typeof input.emails === "string" ? input.emails.split(/[,;]/) : [...input.emails];
392
+ found.sentTo.push(emails.map((email) => email.trim()).filter(Boolean));
393
+ })
394
+ },
395
+ taxpayer: { query: (taxNumber) => run("taxpayer.query", [taxNumber], () => {
396
+ const taxpayerId = taxNumber.replace(/\D/g, "").slice(0, 8);
397
+ return options.taxpayers?.[taxpayerId] ?? {
398
+ valid: false,
399
+ addresses: []
400
+ };
401
+ }) },
402
+ verifyCredentials: () => run("verifyCredentials", [], () => options.credentialsValid ?? true),
403
+ resetSession: () => run("resetSession", [], () => void 0)
404
+ };
405
+ }
406
+ //#endregion
407
+ export { MOCK_PDF, createMockKassza };
@@ -0,0 +1,26 @@
1
+ //#region src/storage/types.d.ts
2
+ interface StoredFile {
3
+ readonly key: string;
4
+ readonly url?: string | undefined;
5
+ readonly size: number;
6
+ readonly contentType: string;
7
+ }
8
+ interface StoragePutOptions {
9
+ readonly contentType: string;
10
+ }
11
+ interface StorageUrlOptions {
12
+ readonly expiresInSeconds?: number | undefined;
13
+ }
14
+ interface StorageAdapter {
15
+ put(key: string, body: Uint8Array, options: StoragePutOptions): Promise<StoredFile>;
16
+ get?(key: string): Promise<Uint8Array | undefined>;
17
+ delete?(key: string): Promise<void>;
18
+ getUrl?(key: string, options?: StorageUrlOptions): Promise<string>;
19
+ }
20
+ interface CompleteStorageAdapter extends StorageAdapter {
21
+ get(key: string): Promise<Uint8Array | undefined>;
22
+ delete(key: string): Promise<void>;
23
+ getUrl(key: string, options?: StorageUrlOptions): Promise<string>;
24
+ }
25
+ //#endregion
26
+ export { StoredFile as a, StorageUrlOptions as i, StorageAdapter as n, StoragePutOptions as r, CompleteStorageAdapter as t };
@@ -0,0 +1,26 @@
1
+ //#region src/storage/types.d.ts
2
+ interface StoredFile {
3
+ readonly key: string;
4
+ readonly url?: string | undefined;
5
+ readonly size: number;
6
+ readonly contentType: string;
7
+ }
8
+ interface StoragePutOptions {
9
+ readonly contentType: string;
10
+ }
11
+ interface StorageUrlOptions {
12
+ readonly expiresInSeconds?: number | undefined;
13
+ }
14
+ interface StorageAdapter {
15
+ put(key: string, body: Uint8Array, options: StoragePutOptions): Promise<StoredFile>;
16
+ get?(key: string): Promise<Uint8Array | undefined>;
17
+ delete?(key: string): Promise<void>;
18
+ getUrl?(key: string, options?: StorageUrlOptions): Promise<string>;
19
+ }
20
+ interface CompleteStorageAdapter extends StorageAdapter {
21
+ get(key: string): Promise<Uint8Array | undefined>;
22
+ delete(key: string): Promise<void>;
23
+ getUrl(key: string, options?: StorageUrlOptions): Promise<string>;
24
+ }
25
+ //#endregion
26
+ export { StoredFile as a, StorageUrlOptions as i, StorageAdapter as n, StoragePutOptions as r, CompleteStorageAdapter as t };