@orvello/sdk 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.
- package/CONTRACT_SHA256 +1 -0
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/contract.cjs +4968 -0
- package/dist/contract.cjs.map +1 -0
- package/dist/contract.d.cts +30468 -0
- package/dist/contract.d.ts +30468 -0
- package/dist/contract.js +4937 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.cjs +748 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +222 -0
- package/dist/index.d.ts +222 -0
- package/dist/index.js +737 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi.json +53764 -0
- package/package.json +86 -0
package/CONTRACT_SHA256
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4efd4e4b669168c9cab5419fa04dd4e26a2029de2d4b10a59918e366189e1072
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Niccas Williams
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# `@orvello/sdk`
|
|
2
|
+
|
|
3
|
+
Typed, zero-dependency SDK for integrating Node and Next.js applications with **orvello** — the
|
|
4
|
+
accounting, invoicing, bookkeeping, customer-company and payments platform.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **End-to-End Typed**: Autogenerated DTOs, request bodies, and responses directly from the
|
|
9
|
+
orvello service contract.
|
|
10
|
+
- **Contract Verification**: Built-in runtime diagnostic (`diagnoseOrvello`) to verify that the
|
|
11
|
+
orvello service you point at speaks the exact contract compiled into the SDK.
|
|
12
|
+
- **Robust HTTP Engine**:
|
|
13
|
+
- Automatic unwrapping of `ApiEnvelope<T>` returning data directly.
|
|
14
|
+
- Automatic retry with exponential backoff on retriable errors (5xx, 429, network failures).
|
|
15
|
+
- Native PDF and binary blob streaming (`Blob`).
|
|
16
|
+
- `Idempotency-Key` support for safe webhooks and financial mutations.
|
|
17
|
+
- **Zero Runtime Dependencies**: Uses native Fetch and WebCrypto.
|
|
18
|
+
- **Flexible Auth**: Supports static API Keys, Bearer tokens, async token getters, and OAuth2
|
|
19
|
+
Client Credentials with automatic token caching.
|
|
20
|
+
- **Ergonomic Accounting Helpers**: Bank account caching (`getDefaultBankAccount`), base64 receipt
|
|
21
|
+
attachments (`buildBase64Receipt`), VAT calculations (`calculateVat`), and Kleinunternehmer
|
|
22
|
+
detection (`isKleinunternehmer`).
|
|
23
|
+
|
|
24
|
+
> **No baked-in endpoint.** This SDK deliberately ships without a fixed target URL. Every
|
|
25
|
+
> `OrvelloClient` — and every `diagnoseOrvello` call — must be pointed at an orvello platform URL
|
|
26
|
+
> explicitly (see below). Nothing quietly aims at a hidden default host.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add @orvello/sdk
|
|
34
|
+
# or
|
|
35
|
+
npm install @orvello/sdk
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { createOrvelloClient, type BaseUrlProvider } from "@orvello/sdk";
|
|
44
|
+
|
|
45
|
+
// Point the client at your orvello deployment explicitly.
|
|
46
|
+
// baseUrl can be a plain string, a function returning a string/Promise, or come from ORVELLO_URL.
|
|
47
|
+
const orvello = createOrvelloClient({
|
|
48
|
+
baseUrl: process.env.ORVELLO_URL!, // e.g. "https://your-org.orvello.example"
|
|
49
|
+
auth: {
|
|
50
|
+
clientId: process.env.ORVELLO_CLIENT_ID!,
|
|
51
|
+
clientSecret: process.env.ORVELLO_CLIENT_SECRET!,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// API Key / Bearer token alternative:
|
|
56
|
+
// const orvello = createOrvelloClient({
|
|
57
|
+
// baseUrl: process.env.ORVELLO_URL!,
|
|
58
|
+
// auth: { apiKey: process.env.ORVELLO_API_KEY! },
|
|
59
|
+
// });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Environment-driven configuration
|
|
63
|
+
|
|
64
|
+
`OrvelloClient` also auto-discovers its target and credentials from `ORVELLO_*` variables when no
|
|
65
|
+
explicit `baseUrl`/`auth` is given:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
ORVELLO_URL=https://your-org.orvello.example
|
|
69
|
+
ORVELLO_OAUTH_CLIENT_ID=...
|
|
70
|
+
ORVELLO_OAUTH_CLIENT_SECRET=...
|
|
71
|
+
# optional
|
|
72
|
+
ORVELLO_OAUTH_SCOPE=...
|
|
73
|
+
# or instead of OAuth:
|
|
74
|
+
ORVELLO_API_KEY=...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// No config object at all — resolves ORVELLO_URL + any ORVELLO_* credentials.
|
|
79
|
+
const orvello = createOrvelloClient();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If neither a `baseUrl` nor `ORVELLO_URL` is present, construction throws a clear error instead of
|
|
83
|
+
silently pointing at a fixed host.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Usage Examples
|
|
88
|
+
|
|
89
|
+
### 1. Invoices
|
|
90
|
+
|
|
91
|
+
#### Create an Invoice
|
|
92
|
+
```typescript
|
|
93
|
+
const result = await orvello.invoices.create({
|
|
94
|
+
invoiceDate: "2026-09-05",
|
|
95
|
+
dueDate: "2026-09-19",
|
|
96
|
+
currency: "EUR",
|
|
97
|
+
customerName: "Acme Corp",
|
|
98
|
+
customerEmail: "accounting@acme.com",
|
|
99
|
+
issueImmediately: true,
|
|
100
|
+
generatePdf: true,
|
|
101
|
+
lineItems: [
|
|
102
|
+
{ title: "Web Development Services", quantity: 1, unitPriceNet: "1500.00", taxRate: 19 },
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
console.log("Created invoice:", result.invoice.invoiceNumber);
|
|
107
|
+
console.log("PDF URL:", result.pdfUrl);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### Download Invoice PDF
|
|
111
|
+
```typescript
|
|
112
|
+
// As a binary Blob
|
|
113
|
+
const pdfBlob = await orvello.invoices.downloadPdf(result.invoice.id);
|
|
114
|
+
|
|
115
|
+
// Or from a relative/direct URL
|
|
116
|
+
const pdfFromUrl = await orvello.invoices.downloadPdfFromUrl(result.pdfUrl!);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Settle an Invoice (Mark as Paid & Reconcile)
|
|
120
|
+
```typescript
|
|
121
|
+
await orvello.invoices.updateStatus(result.invoice.id, {
|
|
122
|
+
status: "paid",
|
|
123
|
+
paymentReference: "STRIPE-PI-998877",
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Or use One-Shot Settlement with payment account and fee deduction:
|
|
127
|
+
const settlement = await orvello.bookkeeping.payments.settleInvoice({
|
|
128
|
+
invoiceId: result.invoice.id,
|
|
129
|
+
paymentAccountId: 1, // e.g. Stripe Account
|
|
130
|
+
payoutAmount: "1735.00", // net received after Stripe fee
|
|
131
|
+
paymentDate: "2026-09-05",
|
|
132
|
+
externalRef: "stripe-charge-ch_12345",
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Issue a Credit Note / Cancellation
|
|
137
|
+
```typescript
|
|
138
|
+
// Preview first (GoBD compliant)
|
|
139
|
+
const preview = await orvello.invoices.previewCreditNote(result.invoice.id, {
|
|
140
|
+
mode: "full",
|
|
141
|
+
reason: "Customer cancellation within 14 days",
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Issue the credit note
|
|
145
|
+
const creditNote = await orvello.invoices.issueCreditNote(result.invoice.id, {
|
|
146
|
+
mode: "full",
|
|
147
|
+
reason: "Customer cancellation within 14 days",
|
|
148
|
+
});
|
|
149
|
+
console.log("Credit note issued:", creditNote.invoice.invoiceNumber);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### 2. Bookkeeping & Expenses with Receipt Upload
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { buildBase64Receipt } from "@orvello/sdk";
|
|
158
|
+
import fs from "node:fs/promises";
|
|
159
|
+
|
|
160
|
+
const fileBuffer = await fs.readFile("./receipt.pdf");
|
|
161
|
+
const receipt = buildBase64Receipt(fileBuffer, "server-hosting.pdf", "application/pdf");
|
|
162
|
+
|
|
163
|
+
const expense = await orvello.bookkeeping.expenses.create(
|
|
164
|
+
{
|
|
165
|
+
managingCompanyId: 1,
|
|
166
|
+
expenseDate: "2026-09-01",
|
|
167
|
+
grossAmount: "119.00",
|
|
168
|
+
netAmount: "100.00",
|
|
169
|
+
taxAmount: "19.00",
|
|
170
|
+
taxRate: "19.00",
|
|
171
|
+
paymentMethod: "bank",
|
|
172
|
+
description: "Hetzner Dedicated Server",
|
|
173
|
+
externalRef: "hetzner-inv-2026-09",
|
|
174
|
+
},
|
|
175
|
+
{ receipt }
|
|
176
|
+
);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### 3. Payment Accounts & Default Bank Account
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// Retrieve the default bank account (cached for 5 minutes)
|
|
185
|
+
const bank = await orvello.bookkeeping.getDefaultBankAccount();
|
|
186
|
+
console.log(`IBAN: ${bank.iban}, BIC: ${bank.bic}, Bank: ${bank.bank}`);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### 4. Managing Company Context & Kleinunternehmer Detection
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { isKleinunternehmer } from "@orvello/sdk";
|
|
195
|
+
|
|
196
|
+
const context = await orvello.managingCompanies.getCurrent();
|
|
197
|
+
if (isKleinunternehmer(context)) {
|
|
198
|
+
console.log("Managing company is Kleinunternehmer (§ 19 UStG) - no VAT shown.");
|
|
199
|
+
} else {
|
|
200
|
+
console.log("Standard taxation (19% VAT).");
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### 5. Dunning / Mahnwesen
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// Get overdue invoices ready for dunning
|
|
210
|
+
const suggestions = await orvello.dunning.suggestions({ limit: 10 });
|
|
211
|
+
|
|
212
|
+
// Issue dunning notice
|
|
213
|
+
for (const item of suggestions.items) {
|
|
214
|
+
if (item.suggestedLevel) {
|
|
215
|
+
const notice = await orvello.dunning.issue(item.invoiceId, { level: item.suggestedLevel });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### 6. Contract Integrity & Health Diagnostic
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { diagnoseOrvello } from "@orvello/sdk";
|
|
226
|
+
|
|
227
|
+
// Pointed at the same platform (client carries a baseUrl) — no baked-in target here either.
|
|
228
|
+
const health = await diagnoseOrvello({ client: orvello });
|
|
229
|
+
if (!health.ok) {
|
|
230
|
+
console.warn("orvello service problem or contract drift:", health.problems);
|
|
231
|
+
} else {
|
|
232
|
+
console.log("orvello service is healthy and contract matches the SDK!");
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Contract Types Re-Export
|
|
239
|
+
|
|
240
|
+
All generated DTOs, request types, and response types are re-exported under `@orvello/sdk/contract`:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import type {
|
|
244
|
+
InvoicesCreateExternalBody,
|
|
245
|
+
InvoicesGetByIdExternalResponseData,
|
|
246
|
+
CustomerCompany,
|
|
247
|
+
Invoice,
|
|
248
|
+
PaymentAccount,
|
|
249
|
+
} from "@orvello/sdk/contract";
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
> **A note on generated names.** The contract subpath re-exports the raw platform contract, which is
|
|
253
|
+
> produced by the accounting backend itself. Some DTOs there carry the backend's internal prefixes
|
|
254
|
+
> (e.g. `NodeBillUser`, `NodeBillAppPermissions`). Those are the unchanged, authoritative types of
|
|
255
|
+
> the backend schema — the SDK only mirrors them. If the backend ever renames them it will flow
|
|
256
|
+
> through automatically via `api:generate`/`sync:contract`; do not hand-edit them here.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT
|