@orvello/sdk 0.1.0 → 0.2.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.
- package/README.md +151 -0
- package/dist/index.cjs +1070 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +416 -1
- package/dist/index.d.ts +416 -1
- package/dist/index.js +1063 -9
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
package/dist/index.d.cts
CHANGED
|
@@ -83,6 +83,267 @@ declare function formatAmount(amount: number | string, currency?: string, locale
|
|
|
83
83
|
*/
|
|
84
84
|
declare function mapPaymentAccountToBankDetails(account: PaymentAccount): BankAccountDetails;
|
|
85
85
|
|
|
86
|
+
type RouteChannelCode = "b" | "k" | "n";
|
|
87
|
+
type RouteIndexEntry = readonly [
|
|
88
|
+
method: string,
|
|
89
|
+
path: string,
|
|
90
|
+
channel: RouteChannelCode,
|
|
91
|
+
authType: string,
|
|
92
|
+
validated: number,
|
|
93
|
+
scopes?: readonly string[]
|
|
94
|
+
];
|
|
95
|
+
declare const ROUTE_INDEX: Readonly<Record<string, RouteIndexEntry>>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Die Route entscheidet, welches Credential mitgeht — nicht der Aufrufer.
|
|
99
|
+
*
|
|
100
|
+
* orvello (node-bill) kennt zwei Bahnen nebeneinander, und sie sind nicht
|
|
101
|
+
* austauschbar:
|
|
102
|
+
*
|
|
103
|
+
* - **bearer** — die Geschaeftsrouten (`unified_bearer`, `frontend_*`). Hier gilt
|
|
104
|
+
* ein OAuth2-Client (client_credentials) oder ein als Bearer gesendeter Token.
|
|
105
|
+
* Das Credential gehoert der *rufenden App*.
|
|
106
|
+
* - **api_key** — die Verwaltungsrouten (`x_api_key_https`), also alles unter
|
|
107
|
+
* `/oauth/clients/external/*`. Hier gilt der Header `x-api-key`. Das Credential
|
|
108
|
+
* gehoert der *Kante* zwischen Verwalter und Dienst.
|
|
109
|
+
*
|
|
110
|
+
* Bis 0.1.0 schickte der Client alles als `Authorization: Bearer`. Die neun
|
|
111
|
+
* Verwaltungsrouten waren damit zwar getippt und aufrufbar, aber grundsaetzlich
|
|
112
|
+
* nicht authentisierbar — ein Loch, das erst beim ersten echten Aufruf sichtbar
|
|
113
|
+
* geworden waere, und dann als `403 Forbidden: Invalid API key` ohne Hinweis auf
|
|
114
|
+
* die Ursache.
|
|
115
|
+
*
|
|
116
|
+
* Der generierte Vertrag traegt `auth.type` an jeder einzelnen Route. Diese Datei
|
|
117
|
+
* liest genau das aus und macht es zur Laufzeitentscheidung. Eine neue Route mit
|
|
118
|
+
* einer neuen Auth-Art faellt damit nicht still in die falsche Bahn, sondern
|
|
119
|
+
* kommt hier an.
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
/** Welche Kopfzeile eine Route verlangt. */
|
|
123
|
+
type OrvelloAuthChannel = "bearer" | "api_key" | "none";
|
|
124
|
+
type OrvelloOperationId = keyof typeof ROUTE_INDEX & string;
|
|
125
|
+
type OrvelloOperation = {
|
|
126
|
+
operationId: string;
|
|
127
|
+
method: string;
|
|
128
|
+
/** Die Vorlage aus dem Vertrag, Platzhalter noch als `:name`. */
|
|
129
|
+
path: string;
|
|
130
|
+
/** Die Auth-Art, wie sie woertlich im Vertrag steht. */
|
|
131
|
+
authType: string;
|
|
132
|
+
/** Was daraus fuer den Aufruf folgt. */
|
|
133
|
+
channel: OrvelloAuthChannel;
|
|
134
|
+
/** Was der Dienst an dieser Route validiert — aus `meta.validated`. */
|
|
135
|
+
validated: {
|
|
136
|
+
params: boolean;
|
|
137
|
+
query: boolean;
|
|
138
|
+
body: boolean;
|
|
139
|
+
};
|
|
140
|
+
/** Die im Vertrag geforderten OAuth2-Scopes, sofern die Auth-Art welche nennt. */
|
|
141
|
+
scopes: readonly string[];
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Bildet eine Auth-Art des Vertrags auf die Bahn ab, ueber die sie bedient wird.
|
|
145
|
+
*
|
|
146
|
+
* Unbekannte Arten landen bewusst auf `bearer`: das ist die Bahn aller
|
|
147
|
+
* Geschaeftsrouten und damit die einzige Voreinstellung, die einen neuen,
|
|
148
|
+
* hier noch nicht gesehenen Routentyp nicht sofort unbrauchbar macht.
|
|
149
|
+
*/
|
|
150
|
+
declare function authChannelForContractType(authType: string | undefined | null): OrvelloAuthChannel;
|
|
151
|
+
/** Alle Operationen des Vertrags, gegen den dieses SDK gebaut wurde. */
|
|
152
|
+
declare function listOperations(): readonly OrvelloOperation[];
|
|
153
|
+
/** Eine Operation nach ihrer `operationId`, oder `null`, wenn der Vertrag sie nicht kennt. */
|
|
154
|
+
declare function describeOperation(operationId: string): OrvelloOperation | null;
|
|
155
|
+
/**
|
|
156
|
+
* Findet die Route, die ein konkreter Pfad anspricht.
|
|
157
|
+
*
|
|
158
|
+
* ⭐ Woertliche Segmente schlagen Platzhalter. Ohne diese Regel wuerde
|
|
159
|
+
* `GET /oauth/clients/external/list` auf `/oauth/clients/external/:idOrClientId`
|
|
160
|
+
* fallen — beide sind GET mit vier Segmenten — und die Auflistung bekaeme die
|
|
161
|
+
* Auth-Entscheidung einer anderen Route. Dass beide hier dieselbe Bahn
|
|
162
|
+
* verlangen, ist Zufall und kein Verlass.
|
|
163
|
+
*/
|
|
164
|
+
declare function resolveOperation(method: string, path: string): OrvelloOperation | null;
|
|
165
|
+
/** Fehlt ein Pfad-Parameter, ist der Aufruf falsch — nicht der Dienst. */
|
|
166
|
+
declare class OrvelloOperationError extends Error {
|
|
167
|
+
readonly operationId: string;
|
|
168
|
+
constructor(message: string, operationId: string);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Setzt die Platzhalter einer Vertrags-Route.
|
|
172
|
+
*
|
|
173
|
+
* Ein fehlender Parameter wirft hier, statt einen Pfad mit `:idOrClientId` darin
|
|
174
|
+
* ans Netz zu geben. Der Dienst antwortete darauf mit 404 oder — schlimmer — mit
|
|
175
|
+
* dem Treffer einer anderen Route.
|
|
176
|
+
*/
|
|
177
|
+
declare function buildPath(operationId: string, params?: Record<string, unknown>): string;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Was dieser Dienst kann — als Daten, ohne Netz und ohne Vermutung.
|
|
181
|
+
*
|
|
182
|
+
* Ein Verbindungs-Verwalter (node-amp) kann Kanten nur dann selbst herstellen,
|
|
183
|
+
* pruefen und reparieren, wenn er weiss, *was die Gegenseite ueberhaupt anbietet*.
|
|
184
|
+
* Bis hierher war das Wissen implizit: irgendwo im Verwalter stand fest
|
|
185
|
+
* einprogrammiert, dass orvello Clients ausstellen kann. Wird eine Faehigkeit dort
|
|
186
|
+
* angenommen und fehlt sie hier, ist das Ergebnis eine Zeile, die gesund aussieht,
|
|
187
|
+
* weil nie jemand gefragt hat.
|
|
188
|
+
*
|
|
189
|
+
* Deshalb leitet sich der Bericht ausschliesslich aus dem mitgelieferten Vertrag
|
|
190
|
+
* ab: eine Faehigkeit gilt genau dann als vorhanden, wenn die zugehoerige
|
|
191
|
+
* Operation im Vertrag steht. Faellt sie in node-bill weg, verschwindet sie beim
|
|
192
|
+
* naechsten `sync:contract` auch hier — niemand muss daran denken.
|
|
193
|
+
*
|
|
194
|
+
* ⚠ Der Bericht sagt, was der Vertrag hergibt, nicht was der Aufrufer darf. Ob ein
|
|
195
|
+
* Credential wirklich traegt, beantwortet allein {@link preflightOrvello}.
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Eine Faehigkeit und die Operationen, an denen sie haengt.
|
|
200
|
+
*
|
|
201
|
+
* `operations` ist der Beleg: wer die Angabe anzweifelt, kann sie gegen den
|
|
202
|
+
* Vertrag nachschlagen, statt dem Wort zu glauben.
|
|
203
|
+
*/
|
|
204
|
+
type OrvelloCapability = {
|
|
205
|
+
supported: boolean;
|
|
206
|
+
operations: string[];
|
|
207
|
+
/** Warum nicht — nur gesetzt, wenn `supported` falsch ist. */
|
|
208
|
+
reason?: string;
|
|
209
|
+
};
|
|
210
|
+
type OrvelloCapabilities = {
|
|
211
|
+
service: "orvello";
|
|
212
|
+
sdkVersion: string;
|
|
213
|
+
contractSha256: string;
|
|
214
|
+
/** Wie viele Operationen der Vertrag insgesamt kennt. */
|
|
215
|
+
operationCount: number;
|
|
216
|
+
/** Welche Credential-Bahnen der Vertrag ueberhaupt verlangt. */
|
|
217
|
+
authChannels: Record<OrvelloAuthChannel, number>;
|
|
218
|
+
capabilities: {
|
|
219
|
+
/** Der Dienst nennt seinen eigenen Vertrags-Fingerabdruck (`GET /health/contract`). */
|
|
220
|
+
contractFingerprint: OrvelloCapability;
|
|
221
|
+
/** Ein unauthentisierter Erreichbarkeits-Endpunkt. */
|
|
222
|
+
healthCheck: OrvelloCapability;
|
|
223
|
+
/** OAuth2-Clients fuer andere Apps anlegen, lesen, aendern, loeschen. */
|
|
224
|
+
clientManagement: OrvelloCapability;
|
|
225
|
+
/** Client-Geheimnis erneuern. */
|
|
226
|
+
clientRotation: OrvelloCapability;
|
|
227
|
+
/**
|
|
228
|
+
* Gnadenfrist beim Wechsel: das alte Geheimnis bleibt gueltig, bis es
|
|
229
|
+
* ausdruecklich zurueckgezogen wird — und laesst sich zurueckdrehen.
|
|
230
|
+
*/
|
|
231
|
+
rotationGracePeriod: OrvelloCapability;
|
|
232
|
+
/** Zugang sofort entziehen. */
|
|
233
|
+
clientRevocation: OrvelloCapability;
|
|
234
|
+
/** Berechtigungen (entitlements) lesen und setzen. */
|
|
235
|
+
entitlements: OrvelloCapability;
|
|
236
|
+
/** Rechnungen ueber die externe API. */
|
|
237
|
+
invoicing: OrvelloCapability;
|
|
238
|
+
/**
|
|
239
|
+
* Ein serverseitiger Probelauf, der schreibt *als ob*, aber nichts aendert.
|
|
240
|
+
*
|
|
241
|
+
* ⭐ Steht hier bewusst mit dem Grund statt still auf `false`: orvello kennt
|
|
242
|
+
* `dryRun` heute nur in der Buchhaltung, nicht in der Client-Verwaltung. Ein
|
|
243
|
+
* Verwalter, der einen Probelauf braucht, nimmt {@link preflightOrvello} —
|
|
244
|
+
* der ist nebenwirkungsfrei, aber er beweist die Berechtigung, nicht das
|
|
245
|
+
* Ergebnis. Der Unterschied gehoert benannt, nicht verschwiegen.
|
|
246
|
+
*/
|
|
247
|
+
serverSideDryRun: OrvelloCapability;
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* Der Faehigkeitsbericht dieses Dienstes. Rein aus dem Vertrag, kein Netzzugriff,
|
|
252
|
+
* kein Credential noetig — damit ein Verwalter ihn auch dann fuehren kann, wenn
|
|
253
|
+
* die Verbindung gerade nicht steht.
|
|
254
|
+
*/
|
|
255
|
+
declare function orvelloCapabilities(): OrvelloCapabilities;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Der Probelauf: "wuerde dieser Aufruf heute klappen?" — ohne ihn zu tun.
|
|
259
|
+
*
|
|
260
|
+
* Ein Verbindungs-Verwalter muss zwei Dinge auseinanderhalten koennen, die sonst
|
|
261
|
+
* gern zusammenfallen: *darf ich* und *habe ich*. Eine Kante anzulegen erzeugt
|
|
262
|
+
* echte Daten auf beiden Seiten; das ist ein freigegebener Schritt und kein
|
|
263
|
+
* Nebenprodukt einer Pruefung. Trotzdem will man jederzeit — auch turnusmaessig,
|
|
264
|
+
* auch ohne Anlass — wissen, ob der Weg noch traegt.
|
|
265
|
+
*
|
|
266
|
+
* Genau diese Luecke fuellt der Probelauf. Er geht denselben Weg wie der echte
|
|
267
|
+
* Aufruf: dieselbe Basis-URL, dieselbe Credential-Bahn, derselbe Vertrag. Er
|
|
268
|
+
* hoert nur vor dem Schreiben auf. Was er beweist, ist die **Berechtigung**, nicht
|
|
269
|
+
* das **Ergebnis** — und dieser Unterschied steht in jedem Bericht, damit ihn
|
|
270
|
+
* niemand ueberliest.
|
|
271
|
+
*
|
|
272
|
+
* ⭐ Jeder Schritt traegt seinen Grund. Ein `ok: false` ohne Satz ist genau die
|
|
273
|
+
* schweigende Luecke, die aussieht wie Gesundheit.
|
|
274
|
+
*/
|
|
275
|
+
|
|
276
|
+
type PreflightStepName = "operation" | "path-parameters" | "request-shape" | "reachable" | "contract" | "credential-configured" | "credential-accepted";
|
|
277
|
+
type PreflightStep = {
|
|
278
|
+
name: PreflightStepName;
|
|
279
|
+
ok: boolean;
|
|
280
|
+
/** Uebersprungen heisst: nicht gepruefft. Nie "in Ordnung". */
|
|
281
|
+
skipped: boolean;
|
|
282
|
+
/** Was geprueft wurde und was dabei herauskam — in Worten, nicht als Code. */
|
|
283
|
+
detail: string;
|
|
284
|
+
};
|
|
285
|
+
type PreflightReport = {
|
|
286
|
+
ok: boolean;
|
|
287
|
+
operationId: string;
|
|
288
|
+
method: string | null;
|
|
289
|
+
/** Der Pfad, der wirklich gerufen wuerde — Platzhalter bereits gesetzt. */
|
|
290
|
+
path: string | null;
|
|
291
|
+
baseUrl: string | null;
|
|
292
|
+
authChannel: OrvelloAuthChannel | null;
|
|
293
|
+
/**
|
|
294
|
+
* Immer `"none"`. Ein Probelauf schreibt nicht — das ist seine Zusage, nicht
|
|
295
|
+
* eine Eigenschaft des Einzelfalls.
|
|
296
|
+
*/
|
|
297
|
+
sideEffects: "none";
|
|
298
|
+
/**
|
|
299
|
+
* Ob der Dienst selbst einen serverseitigen Probelauf dieser Operation kennt.
|
|
300
|
+
* `false` heisst: das hier ist eine Wegpruefung, keine Ergebnisvorschau.
|
|
301
|
+
*/
|
|
302
|
+
serverSideDryRun: boolean;
|
|
303
|
+
steps: PreflightStep[];
|
|
304
|
+
problems: string[];
|
|
305
|
+
checkedAt: string;
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* Was der Probelauf vom Client braucht. Bewusst schmal gehalten, damit die
|
|
309
|
+
* Pruefung nicht am Client haengt und einzeln testbar bleibt.
|
|
310
|
+
*/
|
|
311
|
+
type PreflightHost = {
|
|
312
|
+
resolveBaseUrl(): Promise<string>;
|
|
313
|
+
fetchImpl(): typeof globalThis.fetch;
|
|
314
|
+
/** Ist fuer diese Bahn ueberhaupt ein Credential hinterlegt? Ohne Netz. */
|
|
315
|
+
hasCredentialFor(channel: OrvelloAuthChannel): Promise<boolean>;
|
|
316
|
+
/**
|
|
317
|
+
* Ein echter, ausschliesslich lesender Aufruf auf derselben Bahn.
|
|
318
|
+
* Beweist, dass das Credential nicht nur da ist, sondern auch angenommen wird.
|
|
319
|
+
*/
|
|
320
|
+
probeCredential(channel: OrvelloAuthChannel, signal?: AbortSignal): Promise<{
|
|
321
|
+
ok: boolean;
|
|
322
|
+
detail: string;
|
|
323
|
+
}>;
|
|
324
|
+
};
|
|
325
|
+
type PreflightOptions = {
|
|
326
|
+
params?: Record<string, unknown>;
|
|
327
|
+
query?: Record<string, unknown>;
|
|
328
|
+
body?: unknown;
|
|
329
|
+
timeoutMs?: number;
|
|
330
|
+
signal?: AbortSignal;
|
|
331
|
+
/**
|
|
332
|
+
* Den teuersten Schritt auslassen: kein echter Aufruf, nur die Frage, ob ein
|
|
333
|
+
* Credential hinterlegt ist. Fuer Massenpruefungen ueber viele Kanten.
|
|
334
|
+
*/
|
|
335
|
+
skipCredentialProbe?: boolean;
|
|
336
|
+
};
|
|
337
|
+
/**
|
|
338
|
+
* Prueft einen Aufrufweg, ohne ihn zu gehen.
|
|
339
|
+
*
|
|
340
|
+
* Die Reihenfolge ist Absicht: erst alles, was ohne Netz entschieden werden kann
|
|
341
|
+
* (Vertrag, Parameter, Gestalt), dann die Erreichbarkeit, dann der Vertrag der
|
|
342
|
+
* laufenden Gegenstelle, zuletzt das Credential. So nennt der Bericht bei einem
|
|
343
|
+
* Fehlschlag die *frueheste* Ursache, statt einen Folgefehler zu melden.
|
|
344
|
+
*/
|
|
345
|
+
declare function preflightOrvello(host: PreflightHost, operationId: string, options?: PreflightOptions): Promise<PreflightReport>;
|
|
346
|
+
|
|
86
347
|
type AuthProvider = string | (() => string | Promise<string>) | {
|
|
87
348
|
apiKey: string;
|
|
88
349
|
} | {
|
|
@@ -91,6 +352,15 @@ type AuthProvider = string | (() => string | Promise<string>) | {
|
|
|
91
352
|
scope?: string;
|
|
92
353
|
tokenUrl?: string;
|
|
93
354
|
};
|
|
355
|
+
/** Ein Wert, der sich auch erst beim Aufruf ergeben darf. */
|
|
356
|
+
type ValueProvider<T> = T | (() => T | Promise<T>);
|
|
357
|
+
type HeadersProvider = ValueProvider<Record<string, string>>;
|
|
358
|
+
interface CircuitBreakerConfig {
|
|
359
|
+
/** Wie viele Fehlschlaege in Folge den Kreis oeffnen. */
|
|
360
|
+
threshold?: number;
|
|
361
|
+
/** Wie lange danach nicht erneut versucht wird, bevor ein Versuch den Kreis prueft. */
|
|
362
|
+
cooldownMs?: number;
|
|
363
|
+
}
|
|
94
364
|
interface OrvelloClientConfig {
|
|
95
365
|
/**
|
|
96
366
|
* Base URL of the orvello accounting/invoicing service this client talks to.
|
|
@@ -101,11 +371,44 @@ interface OrvelloClientConfig {
|
|
|
101
371
|
* throws rather than silently aiming at a fixed host.
|
|
102
372
|
*/
|
|
103
373
|
baseUrl?: BaseUrlProvider;
|
|
374
|
+
/**
|
|
375
|
+
* Das Credential der **Geschaeftsrouten** — ein OAuth2-Client
|
|
376
|
+
* (client_credentials) oder ein fertiger Token. Geht als
|
|
377
|
+
* `Authorization: Bearer` mit. Env: `ORVELLO_OAUTH_CLIENT_ID` /
|
|
378
|
+
* `ORVELLO_OAUTH_CLIENT_SECRET` / `ORVELLO_OAUTH_SCOPE`, ersatzweise
|
|
379
|
+
* `ORVELLO_API_KEY`.
|
|
380
|
+
*/
|
|
104
381
|
auth?: AuthProvider;
|
|
382
|
+
/**
|
|
383
|
+
* Das Credential der **Verwaltungsrouten** (`/oauth/clients/external/*`), also
|
|
384
|
+
* der Header `x-api-key`. Env: `ORVELLO_MANAGEMENT_API_KEY`.
|
|
385
|
+
*
|
|
386
|
+
* ⭐ Das ist bewusst ein zweiter, eigener Wert und keine zweite Schreibweise
|
|
387
|
+
* desselben. Die Geschaeftsrouten gehoeren der rufenden App, die
|
|
388
|
+
* Verwaltungsrouten der Kante zwischen Verwalter und Dienst — wer beides in ein
|
|
389
|
+
* Feld legt, verliert genau die Trennung, die eine Rotation je Kante moeglich
|
|
390
|
+
* macht. Ein Client, der nur Rechnungen schreibt, laesst diesen Wert weg und
|
|
391
|
+
* kann dann auch keine Zugaenge ausstellen. Das ist erwuenscht.
|
|
392
|
+
*/
|
|
393
|
+
managementApiKey?: ValueProvider<string>;
|
|
394
|
+
/**
|
|
395
|
+
* Zusaetzliche Kopfzeilen fuer jede Anfrage. Wird vor der Auth-Kopfzeile
|
|
396
|
+
* angewandt, kann sie also nicht versehentlich ueberschreiben.
|
|
397
|
+
*/
|
|
398
|
+
headers?: HeadersProvider;
|
|
105
399
|
fetch?: typeof globalThis.fetch;
|
|
106
400
|
timeoutMs?: number;
|
|
107
401
|
maxRetries?: number;
|
|
108
402
|
retryBaseDelayMs?: number;
|
|
403
|
+
/**
|
|
404
|
+
* Der Sicherungsautomat. `false` schaltet ihn ab.
|
|
405
|
+
*
|
|
406
|
+
* Wiederholungen helfen gegen einen Aussetzer; sie helfen nicht, wenn die
|
|
407
|
+
* Gegenstelle weg ist — dann verlaengern sie nur jede einzelne Anfrage um das
|
|
408
|
+
* volle Zeitlimit mal Versuche. Der Automat beendet diesen Zustand schnell und
|
|
409
|
+
* laut, statt langsam und leise.
|
|
410
|
+
*/
|
|
411
|
+
circuitBreaker?: CircuitBreakerConfig | false;
|
|
109
412
|
}
|
|
110
413
|
interface RequestOptions {
|
|
111
414
|
query?: Record<string, unknown>;
|
|
@@ -115,7 +418,36 @@ interface RequestOptions {
|
|
|
115
418
|
timeoutMs?: number;
|
|
116
419
|
maxRetries?: number;
|
|
117
420
|
signal?: AbortSignal;
|
|
421
|
+
/**
|
|
422
|
+
* Die Credential-Bahn ausdruecklich setzen. Normalerweise unnoetig: der Client
|
|
423
|
+
* liest sie aus dem Vertrag der angesprochenen Route. Nur fuer Pfade gedacht,
|
|
424
|
+
* die der mitgelieferte Vertrag (noch) nicht kennt.
|
|
425
|
+
*/
|
|
426
|
+
authChannel?: OrvelloAuthChannel;
|
|
118
427
|
}
|
|
428
|
+
/** Wie {@link RequestOptions}, aber fuer den Aufruf ueber eine `operationId`. */
|
|
429
|
+
interface CallOptions extends RequestOptions {
|
|
430
|
+
params?: Record<string, unknown>;
|
|
431
|
+
body?: unknown;
|
|
432
|
+
}
|
|
433
|
+
type OrvelloHealth = {
|
|
434
|
+
/** Antwortet der Dienst ueberhaupt? */
|
|
435
|
+
available: boolean;
|
|
436
|
+
responseTimeMs: number;
|
|
437
|
+
/**
|
|
438
|
+
* Wurde ein Credential wirklich angenommen? `null` heisst: nicht geprueft,
|
|
439
|
+
* weil keines hinterlegt ist — nie "in Ordnung".
|
|
440
|
+
*/
|
|
441
|
+
authenticated: boolean | null;
|
|
442
|
+
error?: string;
|
|
443
|
+
};
|
|
444
|
+
type CircuitBreakerState = {
|
|
445
|
+
open: boolean;
|
|
446
|
+
consecutiveFailures: number;
|
|
447
|
+
lastFailureAt: number | null;
|
|
448
|
+
threshold: number;
|
|
449
|
+
cooldownMs: number;
|
|
450
|
+
};
|
|
119
451
|
declare class OrvelloApiError extends Error {
|
|
120
452
|
readonly status: number;
|
|
121
453
|
readonly statusText: string;
|
|
@@ -130,20 +462,103 @@ declare class OrvelloApiError extends Error {
|
|
|
130
462
|
declare class OrvelloClient {
|
|
131
463
|
readonly baseUrl: BaseUrlProvider;
|
|
132
464
|
private readonly auth?;
|
|
465
|
+
private readonly managementApiKey?;
|
|
466
|
+
private readonly extraHeaders?;
|
|
133
467
|
private readonly doFetch;
|
|
134
468
|
private readonly timeoutMs;
|
|
135
469
|
private readonly maxRetries;
|
|
136
470
|
private readonly retryBaseDelayMs;
|
|
137
471
|
private cachedOAuthToken;
|
|
472
|
+
private readonly breakerThreshold;
|
|
473
|
+
private readonly breakerCooldownMs;
|
|
474
|
+
private breakerFailures;
|
|
475
|
+
private breakerLastFailureAt;
|
|
138
476
|
private _bankAccountCache;
|
|
139
477
|
private _bankAccountCacheTime;
|
|
140
478
|
constructor(config?: OrvelloClientConfig);
|
|
141
479
|
private envBaseUrl;
|
|
142
480
|
private envAuth;
|
|
481
|
+
private envManagementApiKey;
|
|
143
482
|
resolveBaseUrl(): Promise<string>;
|
|
483
|
+
private static resolveValue;
|
|
484
|
+
/**
|
|
485
|
+
* Der Verwaltungs-Schluessel, sofern hinterlegt.
|
|
486
|
+
*
|
|
487
|
+
* Ein leerer String zaehlt als "nicht hinterlegt". Sonst waere die haeufigste
|
|
488
|
+
* Fehlkonfiguration — eine gesetzte, aber leere Umgebungsvariable — von einem
|
|
489
|
+
* echten Wert nicht zu unterscheiden, und der Fehler kaeme erst als `403` vom
|
|
490
|
+
* Dienst zurueck.
|
|
491
|
+
*/
|
|
492
|
+
private resolveManagementApiKey;
|
|
144
493
|
private getAuthHeader;
|
|
145
494
|
private isRetriable;
|
|
146
495
|
request<T = unknown>(path: string, options?: RequestInit & RequestOptions): Promise<T>;
|
|
496
|
+
private recordSuccess;
|
|
497
|
+
private recordFailure;
|
|
498
|
+
/**
|
|
499
|
+
* Ist der Dienst nach aktuellem Wissen ansprechbar?
|
|
500
|
+
*
|
|
501
|
+
* Antwortet ohne Netzzugriff aus dem Zustand des Automaten. Nach Ablauf der
|
|
502
|
+
* Abkuehlzeit gilt er wieder als ansprechbar — der naechste echte Aufruf
|
|
503
|
+
* entscheidet dann, ob das stimmt.
|
|
504
|
+
*/
|
|
505
|
+
isAvailable(): boolean;
|
|
506
|
+
/** Der Zustand des Automaten, unverfaelscht — fuer Diagnose-Oberflaechen. */
|
|
507
|
+
circuitState(): CircuitBreakerState;
|
|
508
|
+
/** Den Automaten von Hand schliessen, etwa nach einer behobenen Stoerung. */
|
|
509
|
+
resetCircuit(): void;
|
|
510
|
+
private assertCircuitClosed;
|
|
511
|
+
/**
|
|
512
|
+
* Eine Operation des Vertrags ueber ihre `operationId` aufrufen.
|
|
513
|
+
*
|
|
514
|
+
* Methode, Pfad und Credential-Bahn kommen aus dem Vertrag; der Aufrufer gibt
|
|
515
|
+
* nur die Werte. Das ist der Weg fuer alles, wofuer es keine getippte Methode
|
|
516
|
+
* gibt — und der Weg, der bei einer neuen Route sofort mitwaechst, statt auf
|
|
517
|
+
* eine Handarbeit in diesem Client zu warten.
|
|
518
|
+
*
|
|
519
|
+
* Der Rueckgabetyp ist bewusst offen: die genauen Typen je Operation stehen im
|
|
520
|
+
* Unterpfad `@orvello/sdk/contract` und werden hier als Typ-Argument gesetzt.
|
|
521
|
+
* Ein `operationId`, den der Vertrag nicht kennt, wirft sofort — nicht erst,
|
|
522
|
+
* wenn der Dienst mit 404 antwortet.
|
|
523
|
+
*/
|
|
524
|
+
call<T = unknown>(operationId: string, options?: CallOptions): Promise<T>;
|
|
525
|
+
/**
|
|
526
|
+
* Steht der Dienst, und wird unser Credential angenommen?
|
|
527
|
+
*
|
|
528
|
+
* ⭐ `available` und `authenticated` sind zwei Fragen, und der Bericht haelt sie
|
|
529
|
+
* auseinander. Ein Dienst, der laeuft, aber unser Credential ablehnt, ist nicht
|
|
530
|
+
* "verfuegbar" im Sinne dessen, der ihn benutzen will — und ein `authenticated:
|
|
531
|
+
* null` heisst "nicht gefragt", nie "in Ordnung".
|
|
532
|
+
*/
|
|
533
|
+
checkHealth(options?: {
|
|
534
|
+
timeoutMs?: number;
|
|
535
|
+
signal?: AbortSignal;
|
|
536
|
+
}): Promise<OrvelloHealth>;
|
|
537
|
+
/** Was der Vertrag hergibt — ohne Netz, ohne Credential. */
|
|
538
|
+
capabilities(): OrvelloCapabilities;
|
|
539
|
+
/** Spricht die laufende Gegenstelle denselben Vertrag wie dieses SDK? */
|
|
540
|
+
diagnose(options?: {
|
|
541
|
+
timeoutMs?: number;
|
|
542
|
+
signal?: AbortSignal;
|
|
543
|
+
}): Promise<OrvelloDiagnosis>;
|
|
544
|
+
/**
|
|
545
|
+
* Wuerde dieser Aufruf heute klappen? Prueft den ganzen Weg — Erreichbarkeit,
|
|
546
|
+
* Vertrag, Credential — und schreibt dabei nichts.
|
|
547
|
+
*
|
|
548
|
+
* Gedacht fuer Verbindungs-Verwalter: eine Kante laesst sich damit turnusmaessig
|
|
549
|
+
* nachpruefen, ohne sie anzufassen, und vor einem freigegebenen Schreibschritt
|
|
550
|
+
* laesst sich zeigen, was er tun wuerde.
|
|
551
|
+
*/
|
|
552
|
+
preflight(operationId: string, options?: PreflightOptions): Promise<PreflightReport>;
|
|
553
|
+
/**
|
|
554
|
+
* Ein ausschliesslich lesender Aufruf auf einer Credential-Bahn.
|
|
555
|
+
*
|
|
556
|
+
* Je Bahn die guenstigste Frage, die ohne Nebenwirkung beantwortet, ob das
|
|
557
|
+
* Credential angenommen wird:
|
|
558
|
+
* - `api_key` → die Auflistung der Zugaenge mit `pageSize=1`
|
|
559
|
+
* - `bearer` → das Holen des Tokens (der Dienst prueft dabei Kennung und Geheimnis)
|
|
560
|
+
*/
|
|
561
|
+
private probeCredential;
|
|
147
562
|
invoices: {
|
|
148
563
|
search: (query?: InvoicesSearchExternalQuery, options?: RequestOptions) => Promise<InvoicesSearchExternalResponseData>;
|
|
149
564
|
getById: (id: number, options?: RequestOptions) => Promise<Invoice>;
|
|
@@ -219,4 +634,4 @@ declare function createOrvelloClient(config?: OrvelloClientConfig): OrvelloClien
|
|
|
219
634
|
|
|
220
635
|
declare const CONTRACT_SHA256 = "4efd4e4b669168c9cab5419fa04dd4e26a2029de2d4b10a59918e366189e1072";
|
|
221
636
|
|
|
222
|
-
export { type AuthProvider, type BankAccountDetails, type BaseUrlProvider, BookkeepingExpensesCreateExternalBody, BookkeepingExpensesCreateExternalResponseData, BookkeepingPaymentsCreateManualExternalBody, BookkeepingPaymentsListAccountsExternalQuery, BookkeepingPaymentsListAccountsExternalResponseData, BookkeepingPaymentsSettleInvoiceExternalBody, BookkeepingPaymentsSettleInvoiceExternalResponseData, BookkeepingRevenue, BookkeepingRevenuesCreateExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalResponseData, CONTRACT_SHA256, CustomerCompaniesCreateExternalBody, CustomerCompaniesSearchExternalQuery, CustomerCompaniesSearchExternalResponseData, CustomerCompaniesUpdateExternalBody, CustomerCompany, DunningGetSettingsExternalResponseData, DunningIssueExternalBody, DunningIssueExternalResponseData, DunningPreviewExternalBody, DunningPreviewExternalResponseData, DunningSuggestionsExternalQuery, DunningSuggestionsExternalResponseData, DunningUpdateSettingsExternalBody, DunningUpdateSettingsExternalResponseData, type ExpenseReceiptUpload, Invoice, InvoicesCreateExternalBody, InvoicesCreateExternalResponseData, InvoicesCreditNoteIssueExternalBody, InvoicesCreditNoteIssueExternalResponseData, InvoicesCreditNotePreviewExternalBody, InvoicesCreditNotePreviewExternalResponseData, InvoicesOverdueExternalResponseData, InvoicesPendingExternalResponseData, InvoicesSearchExternalQuery, InvoicesSearchExternalResponseData, InvoicesSendEmailExternalBody, InvoicesSendEmailExternalResponseData, InvoicesStatusPolicyExternalResponseData, InvoicesUpdateStatusExternalBody, ManagingCompaniesCurrentExternalResponseData, NodeBillUser, Oauth2ExternalClientsCreateBody, Oauth2ExternalClientsCreateResponseData, Oauth2ExternalClientsGetResponseData, Oauth2ExternalClientsListQuery, Oauth2ExternalClientsListResponseData, Oauth2ExternalClientsRetireResponseData, Oauth2ExternalClientsRollbackResponseData, Oauth2ExternalClientsRotateBody, Oauth2ExternalClientsRotateResponseData, Oauth2ExternalClientsUpdateBody, Oauth2ExternalClientsUpdateResponseData, OrvelloApiError, OrvelloClient, type OrvelloClientConfig, type OrvelloContractStatus, type OrvelloDiagnoseOptions, type OrvelloDiagnosis, Payment, PaymentAccount, type RequestOptions, UsersUpdateExternalBody, buildBase64Receipt, calculateVat, createOrvelloClient, diagnoseOrvello, formatAmount, isKleinunternehmer, mapPaymentAccountToBankDetails };
|
|
637
|
+
export { type AuthProvider, type BankAccountDetails, type BaseUrlProvider, BookkeepingExpensesCreateExternalBody, BookkeepingExpensesCreateExternalResponseData, BookkeepingPaymentsCreateManualExternalBody, BookkeepingPaymentsListAccountsExternalQuery, BookkeepingPaymentsListAccountsExternalResponseData, BookkeepingPaymentsSettleInvoiceExternalBody, BookkeepingPaymentsSettleInvoiceExternalResponseData, BookkeepingRevenue, BookkeepingRevenuesCreateExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalResponseData, CONTRACT_SHA256, type CallOptions, type CircuitBreakerConfig, type CircuitBreakerState, CustomerCompaniesCreateExternalBody, CustomerCompaniesSearchExternalQuery, CustomerCompaniesSearchExternalResponseData, CustomerCompaniesUpdateExternalBody, CustomerCompany, DunningGetSettingsExternalResponseData, DunningIssueExternalBody, DunningIssueExternalResponseData, DunningPreviewExternalBody, DunningPreviewExternalResponseData, DunningSuggestionsExternalQuery, DunningSuggestionsExternalResponseData, DunningUpdateSettingsExternalBody, DunningUpdateSettingsExternalResponseData, type ExpenseReceiptUpload, type HeadersProvider, Invoice, InvoicesCreateExternalBody, InvoicesCreateExternalResponseData, InvoicesCreditNoteIssueExternalBody, InvoicesCreditNoteIssueExternalResponseData, InvoicesCreditNotePreviewExternalBody, InvoicesCreditNotePreviewExternalResponseData, InvoicesOverdueExternalResponseData, InvoicesPendingExternalResponseData, InvoicesSearchExternalQuery, InvoicesSearchExternalResponseData, InvoicesSendEmailExternalBody, InvoicesSendEmailExternalResponseData, InvoicesStatusPolicyExternalResponseData, InvoicesUpdateStatusExternalBody, ManagingCompaniesCurrentExternalResponseData, NodeBillUser, Oauth2ExternalClientsCreateBody, Oauth2ExternalClientsCreateResponseData, Oauth2ExternalClientsGetResponseData, Oauth2ExternalClientsListQuery, Oauth2ExternalClientsListResponseData, Oauth2ExternalClientsRetireResponseData, Oauth2ExternalClientsRollbackResponseData, Oauth2ExternalClientsRotateBody, Oauth2ExternalClientsRotateResponseData, Oauth2ExternalClientsUpdateBody, Oauth2ExternalClientsUpdateResponseData, OrvelloApiError, type OrvelloAuthChannel, type OrvelloCapabilities, type OrvelloCapability, OrvelloClient, type OrvelloClientConfig, type OrvelloContractStatus, type OrvelloDiagnoseOptions, type OrvelloDiagnosis, type OrvelloHealth, type OrvelloOperation, OrvelloOperationError, type OrvelloOperationId, Payment, PaymentAccount, type PreflightHost, type PreflightOptions, type PreflightReport, type PreflightStep, type PreflightStepName, type RequestOptions, UsersUpdateExternalBody, type ValueProvider, authChannelForContractType, buildBase64Receipt, buildPath, calculateVat, createOrvelloClient, describeOperation, diagnoseOrvello, formatAmount, isKleinunternehmer, listOperations, mapPaymentAccountToBankDetails, orvelloCapabilities, preflightOrvello, resolveOperation };
|