@kreiseck/kasseneck-api 1.3.0 → 1.4.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 (69) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +112 -1
  3. package/dist/cjs/client/aufrufe.d.ts +2 -2
  4. package/dist/cjs/client/aufrufe.js +30 -0
  5. package/dist/cjs/inventory/api.d.ts +45 -0
  6. package/dist/cjs/inventory/api.js +38 -0
  7. package/dist/cjs/inventory/auth.d.ts +17 -0
  8. package/dist/cjs/inventory/auth.js +27 -0
  9. package/dist/cjs/inventory/endpunkte.d.ts +71 -0
  10. package/dist/cjs/inventory/endpunkte.js +285 -0
  11. package/dist/cjs/inventory/fehler.d.ts +33 -0
  12. package/dist/cjs/inventory/fehler.js +47 -0
  13. package/dist/cjs/inventory/index.d.ts +19 -0
  14. package/dist/cjs/inventory/index.js +64 -0
  15. package/dist/cjs/inventory/lesen.d.ts +38 -0
  16. package/dist/cjs/inventory/lesen.js +294 -0
  17. package/dist/cjs/inventory/typen.d.ts +319 -0
  18. package/dist/cjs/inventory/typen.js +14 -0
  19. package/dist/cjs/inventory/vertrag.d.ts +76 -0
  20. package/dist/cjs/inventory/vertrag.js +166 -0
  21. package/dist/cjs/inventory/webhook.d.ts +50 -0
  22. package/dist/cjs/inventory/webhook.js +110 -0
  23. package/dist/cjs/stored/vokabular.d.ts +1 -1
  24. package/dist/cjs/stored/vokabular.js +1 -1
  25. package/dist/cjs/version.d.ts +1 -1
  26. package/dist/cjs/version.js +1 -1
  27. package/dist/esm/client/aufrufe.d.ts +2 -2
  28. package/dist/esm/client/aufrufe.js +30 -0
  29. package/dist/esm/inventory/api.d.ts +45 -0
  30. package/dist/esm/inventory/api.js +35 -0
  31. package/dist/esm/inventory/auth.d.ts +17 -0
  32. package/dist/esm/inventory/auth.js +24 -0
  33. package/dist/esm/inventory/endpunkte.d.ts +71 -0
  34. package/dist/esm/inventory/endpunkte.js +266 -0
  35. package/dist/esm/inventory/fehler.d.ts +33 -0
  36. package/dist/esm/inventory/fehler.js +40 -0
  37. package/dist/esm/inventory/index.d.ts +19 -0
  38. package/dist/esm/inventory/index.js +18 -0
  39. package/dist/esm/inventory/lesen.d.ts +38 -0
  40. package/dist/esm/inventory/lesen.js +278 -0
  41. package/dist/esm/inventory/typen.d.ts +319 -0
  42. package/dist/esm/inventory/typen.js +13 -0
  43. package/dist/esm/inventory/vertrag.d.ts +76 -0
  44. package/dist/esm/inventory/vertrag.js +163 -0
  45. package/dist/esm/inventory/webhook.d.ts +50 -0
  46. package/dist/esm/inventory/webhook.js +101 -0
  47. package/dist/esm/stored/vokabular.d.ts +1 -1
  48. package/dist/esm/stored/vokabular.js +1 -1
  49. package/dist/esm/version.d.ts +1 -1
  50. package/dist/esm/version.js +1 -1
  51. package/fixtures/hobex-hps-codes.json +1 -1
  52. package/fixtures/invoice-api.schema.json +1 -1
  53. package/fixtures/invoice-texts.json +1 -1
  54. package/fixtures/pos-texts.json +1 -1
  55. package/fixtures/surface.json +161 -3
  56. package/fixtures/v3/README.md +9 -1
  57. package/fixtures/v3/antworten/belege.json +2 -2
  58. package/fixtures/v3/antworten/belegmail.json +2 -2
  59. package/fixtures/v3/antworten/kasse-belege.json +2 -2
  60. package/fixtures/v3/antworten/kasse.json +3 -3
  61. package/fixtures/v3/antworten/lager.json +1520 -0
  62. package/fixtures/v3/antworten/rechnungen.json +2 -2
  63. package/fixtures/v3/antworten/storno.json +2 -2
  64. package/fixtures/v3/stored/belege.json +2 -2
  65. package/fixtures/v3/stored/kasse.json +404 -4
  66. package/fixtures/v3/stored/rechnungen.json +2 -2
  67. package/fixtures/v3/v3-vokabular.json +423 -6
  68. package/fixtures/v3/zahlbetrag-faelle.json +2 -2
  69. package/package.json +14 -2
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Die Aufrufe der Lager-API: Artikel, Standorte, Bestand und Bewegungen
3
+ * lesen, Konto-Webhooks verwalten (Backend Stufe 5a).
4
+ *
5
+ * Jede Funktion nimmt den Transport als ersten Parameter und ist einzeln
6
+ * importierbar; die Fassade [createInventoryClient] bindet ihn nur einmal.
7
+ *
8
+ * **Geprueft wird hier nur, was ohne Netz sicher falsch ist** (leere Kennung,
9
+ * `limit` ausserhalb 1–200, eine Aenderung ohne Feld). Alles Fachliche prueft
10
+ * der Server und meldet es als `validation` mit `errors[]`; zwei Pruefungen
11
+ * hiessen zwei Wahrheiten.
12
+ *
13
+ * Lesen hat keine Wirkung: nach einem Zeitlimit darf derselbe Aufruf
14
+ * wiederholt werden. Bei `rate_limited` vorher `retryAfterSec` warten
15
+ * ([inventoryRetryAfterSec]).
16
+ */
17
+ import type { InternerTransport } from '../client/aufrufe.js';
18
+ import type { Article, ArticleListQuery, ArticleLookup, ArticlePage, CreateInventoryWebhookOptions, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestResult, InventoryWebhookWithSecret, Location, StockLevel, StockListQuery, StockMovement, StockMovementPage, StockMovementQuery, StockPage, StockResult } from './typen.js';
19
+ export declare function getArticle(transport: InternerTransport, articleId: string): Promise<Article>;
20
+ export declare function listArticles(transport: InternerTransport, query?: ArticleListQuery): Promise<ArticlePage>;
21
+ /** Alle Artikel der Abfrage, Seite fuer Seite ueber `nextCursor`. */
22
+ export declare function iterateArticles(transport: InternerTransport, query?: ArticleListQuery): AsyncGenerator<Article, void, undefined>;
23
+ /**
24
+ * Ein aktiver Artikel per Code (`number`, `ean` oder `internalCode`) oder per
25
+ * eigener Kennung aus `externalIds` (`{ externalSystem: 'shop', externalId: '4711' }`).
26
+ * Ein stillgelegter Artikel gilt als nicht gefunden (`article_not_found`).
27
+ */
28
+ export declare function lookupArticleByCode(transport: InternerTransport, lookup: ArticleLookup): Promise<Article>;
29
+ /** Alle Standorte des Kontos, samt aufgeloesten (`active: false`) und dem Hauptstandort. */
30
+ export declare function listLocations(transport: InternerTransport): Promise<Location[]>;
31
+ /** Bestand eines Artikels je Standort. */
32
+ export declare function getStock(transport: InternerTransport, articleId: string): Promise<StockResult>;
33
+ export declare function listStock(transport: InternerTransport, query?: StockListQuery): Promise<StockPage>;
34
+ /**
35
+ * Alle Bestandszeilen der Abfrage, Seite fuer Seite. Die Werte (`values`)
36
+ * stehen je Seite in [listStock]; der Iterator liefert nur die Zeilen.
37
+ */
38
+ export declare function iterateStock(transport: InternerTransport, query?: StockListQuery): AsyncGenerator<StockLevel, void, undefined>;
39
+ /** Das Lagerprotokoll, neueste zuerst. */
40
+ export declare function listStockMovements(transport: InternerTransport, query?: StockMovementQuery): Promise<StockMovementPage>;
41
+ export declare function iterateStockMovements(transport: InternerTransport, query?: StockMovementQuery): AsyncGenerator<StockMovement, void, undefined>;
42
+ /**
43
+ * Legt einen Webhook an (hoechstens 5 je Konto, `webhook_limit`).
44
+ * **Das Secret in der Antwort kommt nur dieses eine Mal**; sofort dorthin
45
+ * schreiben, wo der Empfaenger es liest, nicht in ein Protokoll.
46
+ */
47
+ export declare function createWebhook(transport: InternerTransport, options: CreateInventoryWebhookOptions): Promise<InventoryWebhookWithSecret>;
48
+ /** Aendert nur die genannten Felder; `description: null` loescht die Beschreibung. */
49
+ export declare function updateWebhook(transport: InternerTransport, webhookId: string, patch: InventoryWebhookPatch): Promise<InventoryWebhook>;
50
+ export declare function deleteWebhook(transport: InternerTransport, webhookId: string): Promise<{
51
+ webhookId: string;
52
+ deleted: boolean;
53
+ }>;
54
+ /** Die Webhooks des Kontos und die Ereignisse, die es abonnieren kann. */
55
+ export declare function listWebhooks(transport: InternerTransport): Promise<InventoryWebhookList>;
56
+ /**
57
+ * Ein neues Secret fuer denselben Webhook. Ab der Antwort gilt nur noch das
58
+ * neue (keine Uebergangsfrist): erst speichern, dann weiterarbeiten.
59
+ */
60
+ export declare function rotateWebhookSecret(transport: InternerTransport, webhookId: string): Promise<InventoryWebhookWithSecret>;
61
+ /**
62
+ * Eine Probe genau dieses Ereignisses an genau diesen Webhook, mit erfundener
63
+ * Nutzlast und `test: true` in der Huelle. Der Webhook muss das Ereignis
64
+ * abonnieren (`event_not_subscribed`) und aktiv sein (`webhook_inactive`).
65
+ */
66
+ export declare function sendWebhookTest(transport: InternerTransport, webhookId: string, event: string): Promise<InventoryWebhookTestResult>;
67
+ /** Die letzten Zustellungen, neueste zuerst; mit `webhookId` nur die eines Webhooks. */
68
+ export declare function listWebhookDeliveries(transport: InternerTransport, options?: {
69
+ webhookId?: string;
70
+ limit?: number;
71
+ }): Promise<InventoryWebhookDelivery[]>;
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Die Aufrufe der Lager-API: Artikel, Standorte, Bestand und Bewegungen
3
+ * lesen, Konto-Webhooks verwalten (Backend Stufe 5a).
4
+ *
5
+ * Jede Funktion nimmt den Transport als ersten Parameter und ist einzeln
6
+ * importierbar; die Fassade [createInventoryClient] bindet ihn nur einmal.
7
+ *
8
+ * **Geprueft wird hier nur, was ohne Netz sicher falsch ist** (leere Kennung,
9
+ * `limit` ausserhalb 1–200, eine Aenderung ohne Feld). Alles Fachliche prueft
10
+ * der Server und meldet es als `validation` mit `errors[]`; zwei Pruefungen
11
+ * hiessen zwei Wahrheiten.
12
+ *
13
+ * Lesen hat keine Wirkung: nach einem Zeitlimit darf derselbe Aufruf
14
+ * wiederholt werden. Bei `rate_limited` vorher `retryAfterSec` warten
15
+ * ([inventoryRetryAfterSec]).
16
+ */
17
+ import { KasseneckValidationError } from '../client/errors.js';
18
+ import { antwortfehler, artikel, bestand, bewegung, liste, naechsterCursor, objekt, probeZustellung, standort, webhook, wert, zustellung, } from './lesen.js';
19
+ import { INVENTORY_LIST_LIMIT_MAX } from './vertrag.js';
20
+ function anfragefehler(name, grund) {
21
+ return new KasseneckValidationError(name, grund, 'request');
22
+ }
23
+ /** Eine Kennung, die gesendet werden muss: Text mit mindestens einem Zeichen ausser Leerraum. */
24
+ function kennung(name, feld, wert) {
25
+ if (typeof wert !== 'string' || wert.trim() === '')
26
+ throw anfragefehler(name, `${feld} fehlt`);
27
+ return wert;
28
+ }
29
+ /** Felder, die einen Zeitpunkt tragen: ein `Date` geht als ISO 8601 UTC hinaus. */
30
+ const ZEITFELDER = new Set(['updatedSince', 'changedSince', 'from', 'to']);
31
+ /**
32
+ * Die Abfrage einer Liste als Parameter. Unbekannte Felder gehen unveraendert
33
+ * hinaus (der Server weist sie mit `validation` ab), `undefined` faellt weg.
34
+ */
35
+ function abfrage(name, query) {
36
+ if (query === undefined || query === null)
37
+ return {};
38
+ if (typeof query !== 'object' || Array.isArray(query))
39
+ throw anfragefehler(name, 'Abfrage muss ein Objekt sein');
40
+ const raus = {};
41
+ for (const [feld, w] of Object.entries(query)) {
42
+ if (w === undefined)
43
+ continue;
44
+ if (ZEITFELDER.has(feld) && w instanceof Date) {
45
+ if (Number.isNaN(w.getTime()))
46
+ throw anfragefehler(name, `${feld} ist kein gueltiger Zeitpunkt`);
47
+ raus[feld] = w.toISOString();
48
+ continue;
49
+ }
50
+ raus[feld] = w;
51
+ }
52
+ if (raus.limit !== undefined) {
53
+ const limit = raus.limit;
54
+ if (typeof limit !== 'number' || !Number.isInteger(limit) || limit < 1 || limit > INVENTORY_LIST_LIMIT_MAX) {
55
+ throw anfragefehler(name, `limit muss eine ganze Zahl von 1 bis ${INVENTORY_LIST_LIMIT_MAX} sein`);
56
+ }
57
+ }
58
+ if (raus.cursor !== undefined)
59
+ kennung(name, 'cursor', raus.cursor);
60
+ return raus;
61
+ }
62
+ /**
63
+ * Blaettert ueber alle Seiten, Eintrag fuer Eintrag. Derselbe Cursor zweimal
64
+ * waere eine Endlosschleife: dann endet die Schleife mit einem Antwortfehler.
65
+ */
66
+ async function* seitenweise(name, start, seite) {
67
+ const gesehen = new Set();
68
+ // Auch der Startcursor zaehlt: nennt die erste Antwort ihn wieder, waere es dieselbe Seite.
69
+ if (start)
70
+ gesehen.add(start);
71
+ let cursor = start;
72
+ for (;;) {
73
+ const { eintraege, nextCursor } = await seite(cursor);
74
+ yield* eintraege;
75
+ if (nextCursor === null)
76
+ return;
77
+ if (gesehen.has(nextCursor))
78
+ throw antwortfehler(name, 'Antwort nennt denselben nextCursor zweimal');
79
+ gesehen.add(nextCursor);
80
+ cursor = nextCursor;
81
+ }
82
+ }
83
+ // ---- Artikel ------------------------------------------------------------------
84
+ export async function getArticle(transport, articleId) {
85
+ const name = 'getArticle';
86
+ const daten = await transport(name, { articleId: kennung(name, 'articleId', articleId) });
87
+ return artikel({ name, pfad: 'article' }, objekt(daten)?.article);
88
+ }
89
+ export async function listArticles(transport, query) {
90
+ const name = 'listArticles';
91
+ const daten = await transport(name, abfrage(name, query));
92
+ return { articles: liste(name, daten, 'articles', artikel), nextCursor: naechsterCursor(name, daten) };
93
+ }
94
+ /** Alle Artikel der Abfrage, Seite fuer Seite ueber `nextCursor`. */
95
+ export function iterateArticles(transport, query) {
96
+ const { cursor, ...rest } = query ?? {};
97
+ return seitenweise('listArticles', cursor, async (c) => {
98
+ const s = await listArticles(transport, { ...rest, cursor: c });
99
+ return { eintraege: s.articles, nextCursor: s.nextCursor };
100
+ });
101
+ }
102
+ /**
103
+ * Ein aktiver Artikel per Code (`number`, `ean` oder `internalCode`) oder per
104
+ * eigener Kennung aus `externalIds` (`{ externalSystem: 'shop', externalId: '4711' }`).
105
+ * Ein stillgelegter Artikel gilt als nicht gefunden (`article_not_found`).
106
+ */
107
+ export async function lookupArticleByCode(transport, lookup) {
108
+ const name = 'lookupArticleByCode';
109
+ let params;
110
+ if (typeof lookup === 'string') {
111
+ params = { code: kennung(name, 'code', lookup) };
112
+ }
113
+ else if (lookup !== null && typeof lookup === 'object' && !Array.isArray(lookup)) {
114
+ const l = lookup;
115
+ const extern = l.externalSystem !== undefined || l.externalId !== undefined;
116
+ if (l.code !== undefined && extern)
117
+ throw anfragefehler(name, 'entweder code oder externalSystem mit externalId');
118
+ params = extern
119
+ ? { externalSystem: kennung(name, 'externalSystem', l.externalSystem), externalId: kennung(name, 'externalId', l.externalId) }
120
+ : { code: kennung(name, 'code', l.code) };
121
+ }
122
+ else {
123
+ throw anfragefehler(name, 'Code als Text oder { code } bzw. { externalSystem, externalId } erwartet');
124
+ }
125
+ const daten = await transport(name, params);
126
+ return artikel({ name, pfad: 'article' }, objekt(daten)?.article);
127
+ }
128
+ // ---- Standorte und Bestand -----------------------------------------------------------
129
+ /** Alle Standorte des Kontos, samt aufgeloesten (`active: false`) und dem Hauptstandort. */
130
+ export async function listLocations(transport) {
131
+ const name = 'listLocations';
132
+ return liste(name, await transport(name, {}), 'locations', standort);
133
+ }
134
+ /** Die Werte (`values`): fehlt das Feld, fehlt das Recht `costs` -> `null`, nie `[]`. */
135
+ function werte(name, daten) {
136
+ const roh = objekt(daten)?.values;
137
+ if (roh === undefined || roh === null)
138
+ return null;
139
+ return liste(name, daten, 'values', wert);
140
+ }
141
+ /** Bestand eines Artikels je Standort. */
142
+ export async function getStock(transport, articleId) {
143
+ const name = 'getStock';
144
+ const daten = await transport(name, { articleId: kennung(name, 'articleId', articleId) });
145
+ return { stock: liste(name, daten, 'stock', bestand), values: werte(name, daten) };
146
+ }
147
+ export async function listStock(transport, query) {
148
+ const name = 'listStock';
149
+ const daten = await transport(name, abfrage(name, query));
150
+ return { stock: liste(name, daten, 'stock', bestand), values: werte(name, daten), nextCursor: naechsterCursor(name, daten) };
151
+ }
152
+ /**
153
+ * Alle Bestandszeilen der Abfrage, Seite fuer Seite. Die Werte (`values`)
154
+ * stehen je Seite in [listStock]; der Iterator liefert nur die Zeilen.
155
+ */
156
+ export function iterateStock(transport, query) {
157
+ const { cursor, ...rest } = query ?? {};
158
+ return seitenweise('listStock', cursor, async (c) => {
159
+ const s = await listStock(transport, { ...rest, cursor: c });
160
+ return { eintraege: s.stock, nextCursor: s.nextCursor };
161
+ });
162
+ }
163
+ /** Das Lagerprotokoll, neueste zuerst. */
164
+ export async function listStockMovements(transport, query) {
165
+ const name = 'listStockMovements';
166
+ const daten = await transport(name, abfrage(name, query));
167
+ return { movements: liste(name, daten, 'movements', bewegung), nextCursor: naechsterCursor(name, daten) };
168
+ }
169
+ export function iterateStockMovements(transport, query) {
170
+ const { cursor, ...rest } = query ?? {};
171
+ return seitenweise('listStockMovements', cursor, async (c) => {
172
+ const s = await listStockMovements(transport, { ...rest, cursor: c });
173
+ return { eintraege: s.movements, nextCursor: s.nextCursor };
174
+ });
175
+ }
176
+ // ---- Webhooks ------------------------------------------------------------------
177
+ function mitSecret(name, daten) {
178
+ const o = objekt(daten);
179
+ const secret = o?.secret;
180
+ if (typeof secret !== 'string' || secret === '') {
181
+ throw antwortfehler(name, 'Antwort enthaelt kein secret; ohne es laesst sich keine Zustellung pruefen');
182
+ }
183
+ return { webhook: webhook({ name, pfad: 'webhook' }, o?.webhook), secret };
184
+ }
185
+ /**
186
+ * Legt einen Webhook an (hoechstens 5 je Konto, `webhook_limit`).
187
+ * **Das Secret in der Antwort kommt nur dieses eine Mal**; sofort dorthin
188
+ * schreiben, wo der Empfaenger es liest, nicht in ein Protokoll.
189
+ */
190
+ export async function createWebhook(transport, options) {
191
+ const name = 'createWebhook';
192
+ const url = kennung(name, 'url', options?.url);
193
+ if (!Array.isArray(options.events) || options.events.length === 0) {
194
+ throw anfragefehler(name, 'events ist leer; ein Webhook ohne Ereignis bekaeme nie etwas');
195
+ }
196
+ const params = { url, events: options.events };
197
+ if (options.description !== undefined)
198
+ params.description = options.description;
199
+ return mitSecret(name, await transport(name, params));
200
+ }
201
+ /** Aendert nur die genannten Felder; `description: null` loescht die Beschreibung. */
202
+ export async function updateWebhook(transport, webhookId, patch) {
203
+ const name = 'updateWebhook';
204
+ const id = kennung(name, 'webhookId', webhookId);
205
+ if (patch === null || typeof patch !== 'object' || Array.isArray(patch))
206
+ throw anfragefehler(name, 'patch muss ein Objekt sein');
207
+ const params = { webhookId: id };
208
+ for (const [feld, w] of Object.entries(patch))
209
+ if (w !== undefined)
210
+ params[feld] = w;
211
+ if (Object.keys(params).length === 1)
212
+ throw anfragefehler(name, 'patch nennt keine Aenderung');
213
+ const daten = await transport(name, params);
214
+ return webhook({ name, pfad: 'webhook' }, objekt(daten)?.webhook);
215
+ }
216
+ export async function deleteWebhook(transport, webhookId) {
217
+ const name = 'deleteWebhook';
218
+ const id = kennung(name, 'webhookId', webhookId);
219
+ const o = objekt(await transport(name, { webhookId: id }));
220
+ return { webhookId: typeof o?.webhookId === 'string' && o.webhookId ? o.webhookId : id, deleted: o?.deleted === true };
221
+ }
222
+ /** Die Webhooks des Kontos und die Ereignisse, die es abonnieren kann. */
223
+ export async function listWebhooks(transport) {
224
+ const name = 'listWebhooks';
225
+ const daten = await transport(name, {});
226
+ const ereignisse = objekt(daten)?.events;
227
+ return {
228
+ webhooks: liste(name, daten, 'webhooks', webhook),
229
+ events: Array.isArray(ereignisse) ? ereignisse.filter((e) => typeof e === 'string') : [],
230
+ };
231
+ }
232
+ /**
233
+ * Ein neues Secret fuer denselben Webhook. Ab der Antwort gilt nur noch das
234
+ * neue (keine Uebergangsfrist): erst speichern, dann weiterarbeiten.
235
+ */
236
+ export async function rotateWebhookSecret(transport, webhookId) {
237
+ const name = 'rotateWebhookSecret';
238
+ return mitSecret(name, await transport(name, { webhookId: kennung(name, 'webhookId', webhookId) }));
239
+ }
240
+ /**
241
+ * Eine Probe genau dieses Ereignisses an genau diesen Webhook, mit erfundener
242
+ * Nutzlast und `test: true` in der Huelle. Der Webhook muss das Ereignis
243
+ * abonnieren (`event_not_subscribed`) und aktiv sein (`webhook_inactive`).
244
+ */
245
+ export async function sendWebhookTest(transport, webhookId, event) {
246
+ const name = 'sendWebhookTest';
247
+ const id = kennung(name, 'webhookId', webhookId);
248
+ const ereignis = kennung(name, 'event', event);
249
+ const daten = await transport(name, { webhookId: id, event: ereignis });
250
+ const o = objekt(daten);
251
+ return {
252
+ eventId: typeof o?.eventId === 'string' ? o.eventId : '',
253
+ event: typeof o?.event === 'string' ? o.event : ereignis,
254
+ deliveries: liste(name, daten, 'deliveries', (ort, e) => probeZustellung(ort, e, id)),
255
+ };
256
+ }
257
+ /** Die letzten Zustellungen, neueste zuerst; mit `webhookId` nur die eines Webhooks. */
258
+ export async function listWebhookDeliveries(transport, options = {}) {
259
+ const name = 'listWebhookDeliveries';
260
+ const params = {};
261
+ if (options.webhookId !== undefined)
262
+ params.webhookId = kennung(name, 'webhookId', options.webhookId);
263
+ if (options.limit !== undefined)
264
+ Object.assign(params, abfrage(name, { limit: options.limit }));
265
+ return liste(name, await transport(name, params), 'deliveries', zustellung);
266
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Fehler der Lager-API auswerten: am Code, nie am Text.
3
+ *
4
+ * Es zaehlen die Codes der Lager-Endpunkte ([INVENTORY_ERROR_CODES]) und die,
5
+ * die Anmeldung und Rand auf jedem Aufruf erzeugen koennen
6
+ * ([INVENTORY_REQUEST_ERROR_CODES]). Ein fremder Code ist fuer diese Helfer
7
+ * kein Lager-Fehler: wer darauf verzweigt, tut es bewusst ueber
8
+ * `KasseneckApiError.code`.
9
+ */
10
+ import type { KasseneckApiError } from '../client/errors.js';
11
+ import { type InventoryErrorCode, type InventoryRequestErrorCode } from './vertrag.js';
12
+ /** Ein Code, den ein Lager-Aufruf liefern kann. */
13
+ export type InventoryApiErrorCode = InventoryErrorCode | InventoryRequestErrorCode;
14
+ export declare function isInventoryErrorCode(value: unknown): value is InventoryApiErrorCode;
15
+ /** Der Fehlercode eines geworfenen Fehlers; `undefined`, wenn es keiner der Lager-API ist. */
16
+ export declare function inventoryErrorCode(error: unknown): InventoryApiErrorCode | undefined;
17
+ /** Kurzform fuer `catch (e) { if (isInventoryError(e, 'article_not_found')) … }`. */
18
+ export declare function isInventoryError(error: unknown, code?: InventoryApiErrorCode): error is KasseneckApiError;
19
+ /** Ein Feldfehler aus `data.errors[]` einer `validation`-Antwort. */
20
+ export interface InventoryFieldError {
21
+ /** Feld der gesendeten Anfrage, z. B. `limit` oder `events`. */
22
+ field: string;
23
+ message: string;
24
+ }
25
+ /** Die Feldfehler einer `validation`-Antwort; leer, wenn es keine sind. */
26
+ export declare function inventoryFieldErrors(error: unknown): InventoryFieldError[];
27
+ /**
28
+ * Wie lange `rate_limited` noch gilt, in Sekunden (`data.retryAfterSec`,
29
+ * dasselbe wie die Kopfzeile `Retry-After`). `undefined`, wenn der Fehler kein
30
+ * `rate_limited` ist oder der Server keine Angabe macht. Die Grenze gilt je
31
+ * Konto (etwa 20 Anfragen je Sekunde, kurze Spitzen bis 40).
32
+ */
33
+ export declare function inventoryRetryAfterSec(error: unknown): number | undefined;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Fehler der Lager-API auswerten: am Code, nie am Text.
3
+ *
4
+ * Es zaehlen die Codes der Lager-Endpunkte ([INVENTORY_ERROR_CODES]) und die,
5
+ * die Anmeldung und Rand auf jedem Aufruf erzeugen koennen
6
+ * ([INVENTORY_REQUEST_ERROR_CODES]). Ein fremder Code ist fuer diese Helfer
7
+ * kein Lager-Fehler: wer darauf verzweigt, tut es bewusst ueber
8
+ * `KasseneckApiError.code`.
9
+ */
10
+ import { bekannterCode, feldfehlerVon } from '../client/fehlercodes.js';
11
+ import { INVENTORY_ERROR_CODES, INVENTORY_REQUEST_ERROR_CODES, } from './vertrag.js';
12
+ const BEKANNT = new Set([...INVENTORY_ERROR_CODES, ...INVENTORY_REQUEST_ERROR_CODES]);
13
+ export function isInventoryErrorCode(value) {
14
+ return typeof value === 'string' && BEKANNT.has(value);
15
+ }
16
+ /** Der Fehlercode eines geworfenen Fehlers; `undefined`, wenn es keiner der Lager-API ist. */
17
+ export function inventoryErrorCode(error) {
18
+ return bekannterCode(error, BEKANNT);
19
+ }
20
+ /** Kurzform fuer `catch (e) { if (isInventoryError(e, 'article_not_found')) … }`. */
21
+ export function isInventoryError(error, code) {
22
+ const gefunden = inventoryErrorCode(error);
23
+ return gefunden !== undefined && (code === undefined || gefunden === code);
24
+ }
25
+ /** Die Feldfehler einer `validation`-Antwort; leer, wenn es keine sind. */
26
+ export function inventoryFieldErrors(error) {
27
+ return feldfehlerVon(error);
28
+ }
29
+ /**
30
+ * Wie lange `rate_limited` noch gilt, in Sekunden (`data.retryAfterSec`,
31
+ * dasselbe wie die Kopfzeile `Retry-After`). `undefined`, wenn der Fehler kein
32
+ * `rate_limited` ist oder der Server keine Angabe macht. Die Grenze gilt je
33
+ * Konto (etwa 20 Anfragen je Sekunde, kurze Spitzen bis 40).
34
+ */
35
+ export function inventoryRetryAfterSec(error) {
36
+ if (inventoryErrorCode(error) !== 'rate_limited')
37
+ return undefined;
38
+ const wert = error.details['retryAfterSec'];
39
+ return typeof wert === 'number' && Number.isFinite(wert) && wert >= 0 ? wert : undefined;
40
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `@kreiseck/kasseneck-api/inventory` – die Lager-API: Artikel, Standorte,
3
+ * Bestand und Lagerprotokoll lesen, Konto-Webhooks verwalten und eingehende
4
+ * Zustellungen pruefen (Backend Stufe 5a).
5
+ *
6
+ * Ein eigener Unterpfad wie `invoice`: der `api_key` eines Kontos gehoert auf
7
+ * einen **Server** (etwa das Backend eines Online-Shops) und soll nicht
8
+ * versehentlich in ein Browser-Buendel wandern.
9
+ *
10
+ * Mengen in Tausendstel der Basiseinheit, Geld in Cent, Einkaufspreise in
11
+ * Mikro-Euro; alles Ganzzahlen.
12
+ */
13
+ export { createInventoryClient, type InventoryClient, type InventoryClientOptions } from './api.js';
14
+ export { inventoryKeyAuth, type InventoryKeyAuthOptions } from './auth.js';
15
+ export { isInventoryError, isInventoryErrorCode, inventoryErrorCode, inventoryFieldErrors, inventoryRetryAfterSec, type InventoryApiErrorCode, type InventoryFieldError, } from './fehler.js';
16
+ export { createWebhook, deleteWebhook, getArticle, getStock, iterateArticles, iterateStock, iterateStockMovements, listArticles, listLocations, listStock, listStockMovements, listWebhookDeliveries, listWebhooks, lookupArticleByCode, rotateWebhookSecret, sendWebhookTest, updateWebhook, } from './endpunkte.js';
17
+ export { verifyInventoryWebhookSignature, parseInventoryWebhookEvent, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_TOLERANCE_SEC, type VerifyInventoryWebhookOptions, } from './webhook.js';
18
+ export type { Article, ArticleListQuery, ArticleLookup, ArticlePage, CreateInventoryWebhookOptions, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookEnvelope, InventoryWebhookEvent, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestDelivery, InventoryWebhookTestResult, InventoryWebhookWithSecret, Location, LocationAddress, StockBelowMinimumEventData, StockChangedEventData, StockLevel, StockListQuery, StockMovement, StockMovementLot, StockMovementPage, StockMovementQuery, StockMovementSourceRef, StockPage, StockResult, StockValue, } from './typen.js';
19
+ export { INVENTORY_ENDPOINTS, INVENTORY_ERROR_CODES, INVENTORY_REQUEST_ERROR_CODES, INVENTORY_WEBHOOK_EVENTS, INVENTORY_WEBHOOK_ENVELOPE_FIELDS, INVENTORY_WEBHOOK_LIMIT, INVENTORY_LIST_LIMIT_MAX, LOCATION_TYPES, STOCK_MOVEMENT_TYPES, STOCK_MOVEMENT_SOURCES, STOCK_CONDITIONS, STOCK_CHANGE_CAUSES, WEBHOOK_DELIVERY_STATUSES, type InventoryEndpoint, type InventoryErrorCode, type InventoryRequestErrorCode, type InventoryWebhookEventType, type LocationType, type StockMovementType, type StockMovementSource, type StockCondition, type StockChangeCause, type WebhookDeliveryStatus, } from './vertrag.js';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `@kreiseck/kasseneck-api/inventory` – die Lager-API: Artikel, Standorte,
3
+ * Bestand und Lagerprotokoll lesen, Konto-Webhooks verwalten und eingehende
4
+ * Zustellungen pruefen (Backend Stufe 5a).
5
+ *
6
+ * Ein eigener Unterpfad wie `invoice`: der `api_key` eines Kontos gehoert auf
7
+ * einen **Server** (etwa das Backend eines Online-Shops) und soll nicht
8
+ * versehentlich in ein Browser-Buendel wandern.
9
+ *
10
+ * Mengen in Tausendstel der Basiseinheit, Geld in Cent, Einkaufspreise in
11
+ * Mikro-Euro; alles Ganzzahlen.
12
+ */
13
+ export { createInventoryClient } from './api.js';
14
+ export { inventoryKeyAuth } from './auth.js';
15
+ export { isInventoryError, isInventoryErrorCode, inventoryErrorCode, inventoryFieldErrors, inventoryRetryAfterSec, } from './fehler.js';
16
+ export { createWebhook, deleteWebhook, getArticle, getStock, iterateArticles, iterateStock, iterateStockMovements, listArticles, listLocations, listStock, listStockMovements, listWebhookDeliveries, listWebhooks, lookupArticleByCode, rotateWebhookSecret, sendWebhookTest, updateWebhook, } from './endpunkte.js';
17
+ export { verifyInventoryWebhookSignature, parseInventoryWebhookEvent, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_TOLERANCE_SEC, } from './webhook.js';
18
+ export { INVENTORY_ENDPOINTS, INVENTORY_ERROR_CODES, INVENTORY_REQUEST_ERROR_CODES, INVENTORY_WEBHOOK_EVENTS, INVENTORY_WEBHOOK_ENVELOPE_FIELDS, INVENTORY_WEBHOOK_LIMIT, INVENTORY_LIST_LIMIT_MAX, LOCATION_TYPES, STOCK_MOVEMENT_TYPES, STOCK_MOVEMENT_SOURCES, STOCK_CONDITIONS, STOCK_CHANGE_CAUSES, WEBHOOK_DELIVERY_STATUSES, } from './vertrag.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Leser der Lager-Antworten: aus dem Draht `/v3` werden die Modelle in
3
+ * `typen.ts`. Paketintern, nicht Teil der Oberflaeche.
4
+ *
5
+ * Regel wie beim Lager an der Kasse (`pos/lager.ts`): eine Menge, ein Betrag
6
+ * oder eine Folgenummer ist eine Ganzzahl, sonst endet der Aufruf mit
7
+ * `KasseneckValidationError` (`scope: 'response'`). Ein Ersatzwert wie `0`
8
+ * waere eine falsche Aussage („kein Bestand“ statt „Antwort kaputt“). Texte
9
+ * sind nachsichtiger: ein fehlender oder fremder Wert wird `null`.
10
+ *
11
+ * Optionale Felder (Einkaufswerte, `externalIds` …) erscheinen im Modell nur,
12
+ * wenn der Server sie sendet: „fehlt“ heisst dort „kein Recht“, nicht „leer“.
13
+ */
14
+ import { KasseneckValidationError } from '../client/errors.js';
15
+ import type { Article, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookTestDelivery, Location, StockBelowMinimumEventData, StockChangedEventData, StockLevel, StockMovement, StockValue } from './typen.js';
16
+ type Roh = Record<string, unknown>;
17
+ /** Ein Leser bekommt den Vorgang (fuer die Meldung) und den Pfad im Rumpf. */
18
+ export interface Ort {
19
+ name: string;
20
+ pfad: string;
21
+ }
22
+ export declare function antwortfehler(name: string, grund: string): KasseneckValidationError;
23
+ export declare function objekt(w: unknown): Roh | null;
24
+ export declare function artikel(ort: Ort, w: unknown): Article;
25
+ export declare function standort(ort: Ort, w: unknown): Location;
26
+ export declare function bestand(ort: Ort, w: unknown): StockLevel;
27
+ export declare function wert(ort: Ort, w: unknown): StockValue;
28
+ export declare function bewegung(ort: Ort, w: unknown): StockMovement;
29
+ export declare function webhook(ort: Ort, w: unknown): InventoryWebhook;
30
+ export declare function zustellung(ort: Ort, w: unknown): InventoryWebhookDelivery;
31
+ export declare function probeZustellung(ort: Ort, w: unknown, webhookId: string): InventoryWebhookTestDelivery;
32
+ export declare function bestandGeaendert(ort: Ort, w: unknown): StockChangedEventData;
33
+ export declare function unterMindestbestand(ort: Ort, w: unknown): StockBelowMinimumEventData;
34
+ /** Eine zugesagte Liste `data.<feld>`, Eintrag fuer Eintrag gelesen. */
35
+ export declare function liste<T>(name: string, daten: unknown, feld: string, lesen: (ort: Ort, e: unknown) => T): T[];
36
+ /** Der Cursor der naechsten Seite; `null` am Ende. Etwas anderes als Text oder `null` ist kaputt. */
37
+ export declare function naechsterCursor(name: string, daten: unknown): string | null;
38
+ export {};