@getpeppr/cli 0.4.2 → 0.4.4
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 +9 -7
- package/dist/index.js +42 -20
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ getpeppr --help
|
|
|
17
17
|
|
|
18
18
|
### `getpeppr init` — Scaffold an invoice
|
|
19
19
|
|
|
20
|
-
Generate a starter JSON file
|
|
20
|
+
Generate a starter JSON file suitable for local validation and UBL conversion:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
getpeppr init # creates invoice.json
|
|
@@ -26,7 +26,7 @@ getpeppr init --credit-note # credit note template
|
|
|
26
26
|
getpeppr init --force # overwrite existing file
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
The generated template includes a Belgian seller, a German buyer, and two invoice lines — ready to edit and
|
|
29
|
+
The generated template includes a Belgian seller, a German buyer, and two invoice lines — ready to edit, validate, and convert locally.
|
|
30
30
|
|
|
31
31
|
### `getpeppr validate` — Validate an invoice
|
|
32
32
|
|
|
@@ -82,7 +82,7 @@ Look up any participant registered on the Peppol network:
|
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
# Direct lookup by Peppol ID
|
|
85
|
-
getpeppr lookup 0208:
|
|
85
|
+
getpeppr lookup 0208:0685660237
|
|
86
86
|
|
|
87
87
|
# Search by company name
|
|
88
88
|
getpeppr lookup --name "Dupont"
|
|
@@ -91,7 +91,7 @@ getpeppr lookup --name "Dupont"
|
|
|
91
91
|
getpeppr lookup --name "GmbH" --country DE
|
|
92
92
|
|
|
93
93
|
# JSON output
|
|
94
|
-
getpeppr lookup 0208:
|
|
94
|
+
getpeppr lookup 0208:0685660237 --json
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
| Flag | Description |
|
|
@@ -131,7 +131,7 @@ Send an invoice through the getpeppr API to the Peppol network. Targets sandbox
|
|
|
131
131
|
getpeppr send invoice.json
|
|
132
132
|
|
|
133
133
|
# Quick test — synthesize an invoice from flags (no file needed)
|
|
134
|
-
getpeppr send --to
|
|
134
|
+
getpeppr send --to 9925:BE0314595348 --amount 100 --desc "Test invoice"
|
|
135
135
|
|
|
136
136
|
# Watch delivery status until terminal (60s timeout)
|
|
137
137
|
getpeppr send invoice.json --watch
|
|
@@ -157,6 +157,8 @@ getpeppr send invoice.json --prod
|
|
|
157
157
|
| `--json` | Machine-readable JSON output |
|
|
158
158
|
| `--quiet` | Exit code only, no output |
|
|
159
159
|
|
|
160
|
+
When sending through the API, getpeppr determines the seller from the API key. A `from` party can still be present for local validation and UBL conversion, but the gateway ignores it for delivery.
|
|
161
|
+
|
|
160
162
|
### `getpeppr logout` — Remove stored credentials
|
|
161
163
|
|
|
162
164
|
```bash
|
|
@@ -198,7 +200,7 @@ Scaffolding (`init`), validation, and conversion run fully offline — no API ke
|
|
|
198
200
|
|
|
199
201
|
## Invoice format
|
|
200
202
|
|
|
201
|
-
The input file must be a JSON object matching the getpeppr `InvoiceInput` type
|
|
203
|
+
The input file must be a JSON object matching the getpeppr `InvoiceInput` type. `number`, `to`, and `lines` are required for API sends. The `from` party is included in the scaffold because offline validation and UBL conversion need seller metadata; API sends use the legal entity linked to your key.
|
|
202
204
|
|
|
203
205
|
```json
|
|
204
206
|
{
|
|
@@ -209,7 +211,7 @@ The input file must be a JSON object matching the getpeppr `InvoiceInput` type:
|
|
|
209
211
|
"buyerReference": "PO-2026-042",
|
|
210
212
|
"from": {
|
|
211
213
|
"name": "Dupont & Fils SPRL",
|
|
212
|
-
"peppolId": "0208:
|
|
214
|
+
"peppolId": "0208:0123456789",
|
|
213
215
|
"street": "Avenue Louise 54",
|
|
214
216
|
"city": "Bruxelles",
|
|
215
217
|
"postalCode": "1050",
|
package/dist/index.js
CHANGED
|
@@ -884,7 +884,7 @@ function validateParty(party, path) {
|
|
|
884
884
|
errors.push(error(`${path}.name`, "Business name is required", "BR-06"));
|
|
885
885
|
}
|
|
886
886
|
if (party.peppolId === void 0 || party.peppolId === null || party.peppolId === "") {
|
|
887
|
-
errors.push(error(`${path}.peppolId`, "Peppol participant ID is required", void 0, 'Format: "scheme:id", e.g. "0208:
|
|
887
|
+
errors.push(error(`${path}.peppolId`, "Peppol participant ID is required", void 0, 'Format: "scheme:id", e.g. "0208:0123456789" for Belgian companies'));
|
|
888
888
|
} else if (!assertString(party.peppolId, `${path}.peppolId`, errors)) {
|
|
889
889
|
} else if (!party.peppolId.includes(":")) {
|
|
890
890
|
errors.push(error(`${path}.peppolId`, `Invalid Peppol ID format: "${party.peppolId}"`, void 0, 'Must be "scheme:id" format. Common schemes: 0208 (Belgium), 0009 (France SIRET), 0204 (Germany Leitweg)'));
|
|
@@ -986,7 +986,7 @@ function validateInvoice(input) {
|
|
|
986
986
|
}
|
|
987
987
|
const ppId = input.payeeParty.peppolId;
|
|
988
988
|
if (ppId === void 0 || ppId === null || ppId === "") {
|
|
989
|
-
errors.push(error("payeeParty.peppolId", "Payee party Peppol ID is required", void 0, 'Format: "scheme:id", e.g. "0208:
|
|
989
|
+
errors.push(error("payeeParty.peppolId", "Payee party Peppol ID is required", void 0, 'Format: "scheme:id", e.g. "0208:0123456789"'));
|
|
990
990
|
} else if (!assertString(ppId, "payeeParty.peppolId", errors)) {
|
|
991
991
|
} else if (!ppId.includes(":")) {
|
|
992
992
|
errors.push(error("payeeParty.peppolId", `Invalid Peppol ID format: "${ppId}"`, void 0, 'Must be "scheme:id" format'));
|
|
@@ -1059,7 +1059,7 @@ function validateInvoice(input) {
|
|
|
1059
1059
|
}
|
|
1060
1060
|
|
|
1061
1061
|
// ../sdk/dist/version.js
|
|
1062
|
-
var SDK_VERSION = "1.
|
|
1062
|
+
var SDK_VERSION = "1.5.1";
|
|
1063
1063
|
|
|
1064
1064
|
// ../sdk/dist/core/client.js
|
|
1065
1065
|
function findHeaderCaseInsensitive(headers, name) {
|
|
@@ -1819,8 +1819,8 @@ ${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (
|
|
|
1819
1819
|
* ```ts
|
|
1820
1820
|
* const result = await peppol.invoices.send({
|
|
1821
1821
|
* number: "INV-001",
|
|
1822
|
-
* from: { name: "My Company", peppolId: "0208:
|
|
1823
|
-
* to: { name: "Client Co", peppolId: "0208:
|
|
1822
|
+
* from: { name: "My Company", peppolId: "0208:0123456789", country: "BE" },
|
|
1823
|
+
* to: { name: "Client Co", peppolId: "0208:0987654321", country: "BE" },
|
|
1824
1824
|
* lines: [
|
|
1825
1825
|
* { description: "Consulting", quantity: 10, unitPrice: 150, vatRate: 21 }
|
|
1826
1826
|
* ]
|
|
@@ -1874,20 +1874,21 @@ ${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (
|
|
|
1874
1874
|
return this.adapter.getInvoiceAs(id, format);
|
|
1875
1875
|
}
|
|
1876
1876
|
/**
|
|
1877
|
-
* Validate an invoice server-side using
|
|
1878
|
-
*
|
|
1879
|
-
*
|
|
1877
|
+
* Validate an invoice server-side using the getpeppr gateway's offline SDK-backed checks.
|
|
1878
|
+
* The gateway runs SDK validation, verifies UBL XML generation, and evaluates offline
|
|
1879
|
+
* Peppol business rules without sending the invoice to Storecove.
|
|
1880
1880
|
*
|
|
1881
1881
|
* @example
|
|
1882
1882
|
* ```ts
|
|
1883
1883
|
* const result = await peppol.invoices.validateServer({
|
|
1884
1884
|
* number: "INV-001",
|
|
1885
|
-
* to: { name: "Acme", peppolId: "0208:
|
|
1885
|
+
* to: { name: "Acme", peppolId: "0208:0123456789", country: "BE" },
|
|
1886
1886
|
* lines: [{ description: "Item", quantity: 1, unitPrice: 100, vatRate: 21 }]
|
|
1887
1887
|
* });
|
|
1888
1888
|
* console.log(result.valid, result.schematron.errors);
|
|
1889
1889
|
* ```
|
|
1890
|
-
*
|
|
1890
|
+
* Validation findings return a structured result with valid=false. Transport, auth,
|
|
1891
|
+
* malformed request, and unexpected gateway failures still throw PeppolApiError.
|
|
1891
1892
|
*/
|
|
1892
1893
|
async validateServer(input) {
|
|
1893
1894
|
return this.adapter.validateDocumentServer(input);
|
|
@@ -2078,14 +2079,14 @@ var DirectoryOperations = class {
|
|
|
2078
2079
|
*
|
|
2079
2080
|
* @example
|
|
2080
2081
|
* ```ts
|
|
2081
|
-
* const entry = await peppol.directory.lookup("0208:
|
|
2082
|
+
* const entry = await peppol.directory.lookup("0208:0123456789");
|
|
2082
2083
|
* console.log(entry.name, entry.capabilities);
|
|
2083
2084
|
* ```
|
|
2084
2085
|
*/
|
|
2085
2086
|
async lookup(peppolId) {
|
|
2086
2087
|
const colonIndex = peppolId.indexOf(":");
|
|
2087
2088
|
if (colonIndex === -1) {
|
|
2088
|
-
throw new PeppolError('Invalid Peppol ID format. Expected "scheme:id" (e.g., "0208:
|
|
2089
|
+
throw new PeppolError('Invalid Peppol ID format. Expected "scheme:id" (e.g., "0208:0123456789")');
|
|
2089
2090
|
}
|
|
2090
2091
|
const scheme = peppolId.slice(0, colonIndex);
|
|
2091
2092
|
const id = peppolId.slice(colonIndex + 1);
|
|
@@ -2207,7 +2208,7 @@ var ContactOperations = class {
|
|
|
2207
2208
|
* ```ts
|
|
2208
2209
|
* const contact = await peppol.contacts.create({
|
|
2209
2210
|
* name: "Acme Corp",
|
|
2210
|
-
* peppolId: "0208:
|
|
2211
|
+
* peppolId: "0208:0123456789",
|
|
2211
2212
|
* country: "BE",
|
|
2212
2213
|
* isClient: true,
|
|
2213
2214
|
* });
|
|
@@ -2788,7 +2789,7 @@ var INVOICE_TEMPLATE = {
|
|
|
2788
2789
|
buyerReference: "PO-2026-042",
|
|
2789
2790
|
from: {
|
|
2790
2791
|
name: "Dupont & Fils SPRL",
|
|
2791
|
-
peppolId: "0208:
|
|
2792
|
+
peppolId: "0208:0123456789",
|
|
2792
2793
|
street: "Avenue Louise 54",
|
|
2793
2794
|
city: "Bruxelles",
|
|
2794
2795
|
postalCode: "1050",
|
|
@@ -2830,7 +2831,7 @@ var CREDIT_NOTE_TEMPLATE = {
|
|
|
2830
2831
|
invoiceReference: "INV-2026-001",
|
|
2831
2832
|
from: {
|
|
2832
2833
|
name: "Dupont & Fils SPRL",
|
|
2833
|
-
peppolId: "0208:
|
|
2834
|
+
peppolId: "0208:0123456789",
|
|
2834
2835
|
street: "Avenue Louise 54",
|
|
2835
2836
|
city: "Bruxelles",
|
|
2836
2837
|
postalCode: "1050",
|
|
@@ -2994,7 +2995,7 @@ function parseMatch(raw) {
|
|
|
2994
2995
|
};
|
|
2995
2996
|
}
|
|
2996
2997
|
async function lookupParticipant(scheme, id) {
|
|
2997
|
-
const participantParam = `iso6523-actorid-upis::${scheme}:${id}`;
|
|
2998
|
+
const participantParam = `iso6523-actorid-upis::${scheme}:${normalizeParticipantIdentifier(scheme, id)}`;
|
|
2998
2999
|
const url = `${BASE_URL}?participant=${encodeURIComponent(participantParam)}`;
|
|
2999
3000
|
const response = await fetch(url, {
|
|
3000
3001
|
signal: AbortSignal.timeout(15e3),
|
|
@@ -3012,6 +3013,12 @@ async function lookupParticipant(scheme, id) {
|
|
|
3012
3013
|
}
|
|
3013
3014
|
return parseMatch(data.matches[0]);
|
|
3014
3015
|
}
|
|
3016
|
+
function normalizeParticipantIdentifier(scheme, id) {
|
|
3017
|
+
if (scheme === "0208") {
|
|
3018
|
+
return id.replace(/^BE(?=(?:0|1)\d{9}$)/i, "");
|
|
3019
|
+
}
|
|
3020
|
+
return id;
|
|
3021
|
+
}
|
|
3015
3022
|
async function searchParticipants(opts) {
|
|
3016
3023
|
const params = new URLSearchParams();
|
|
3017
3024
|
if (opts.name) params.set("name", opts.name);
|
|
@@ -3140,7 +3147,7 @@ function validatePeppolId(raw) {
|
|
|
3140
3147
|
if (colonIndex === -1) {
|
|
3141
3148
|
return {
|
|
3142
3149
|
ok: false,
|
|
3143
|
-
error: `Invalid Peppol ID format: "${raw}". Expected format: scheme:id (e.g. 0208:
|
|
3150
|
+
error: `Invalid Peppol ID format: "${raw}". Expected format: scheme:id (e.g. 0208:0685660237)`
|
|
3144
3151
|
};
|
|
3145
3152
|
}
|
|
3146
3153
|
const scheme = raw.slice(0, colonIndex);
|
|
@@ -3395,6 +3402,20 @@ startxref
|
|
|
3395
3402
|
190
|
|
3396
3403
|
%%EOF`;
|
|
3397
3404
|
var MINIMAL_TEST_PDF_BASE64 = Buffer.from(MINIMAL_PDF).toString("base64");
|
|
3405
|
+
var SCHEME_COUNTRY_DEFAULTS = {
|
|
3406
|
+
"0009": "FR",
|
|
3407
|
+
"0204": "DE",
|
|
3408
|
+
"0208": "BE",
|
|
3409
|
+
"9925": "BE"
|
|
3410
|
+
};
|
|
3411
|
+
function deriveCountryFromPeppolId(peppolId) {
|
|
3412
|
+
const [scheme, identifier = ""] = peppolId.split(":");
|
|
3413
|
+
const alphaPrefix = identifier.slice(0, 2);
|
|
3414
|
+
if (/^[A-Za-z]{2}$/.test(alphaPrefix)) {
|
|
3415
|
+
return alphaPrefix.toUpperCase();
|
|
3416
|
+
}
|
|
3417
|
+
return SCHEME_COUNTRY_DEFAULTS[scheme] ?? "BE";
|
|
3418
|
+
}
|
|
3398
3419
|
function buildDefaultSendPayload(overrides = {}) {
|
|
3399
3420
|
const today = /* @__PURE__ */ new Date();
|
|
3400
3421
|
const due = new Date(today.getTime() + 30 * 864e5);
|
|
@@ -3406,7 +3427,7 @@ function buildDefaultSendPayload(overrides = {}) {
|
|
|
3406
3427
|
const description = overrides.description ?? "Test service from getpeppr";
|
|
3407
3428
|
const randomSuffix = Math.floor(Math.random() * 65536).toString(16).toUpperCase().padStart(4, "0");
|
|
3408
3429
|
const number = `TEST-${Date.now().toString(36).toUpperCase()}-${randomSuffix}`;
|
|
3409
|
-
const country =
|
|
3430
|
+
const country = overrides.country != null ? overrides.country.toUpperCase() : deriveCountryFromPeppolId(peppolId);
|
|
3410
3431
|
const payload = {
|
|
3411
3432
|
number,
|
|
3412
3433
|
date: isoToday,
|
|
@@ -3458,7 +3479,7 @@ var MutexError = class extends Error {
|
|
|
3458
3479
|
function hasOverrides(o) {
|
|
3459
3480
|
if (!o) return false;
|
|
3460
3481
|
return Boolean(
|
|
3461
|
-
o.to != null && o.to !== "" || o.amount != null || o.currency || o.description || o.attachment === true
|
|
3482
|
+
o.to != null && o.to !== "" || o.country != null && o.country !== "" || o.amount != null || o.currency || o.description || o.attachment === true
|
|
3462
3483
|
);
|
|
3463
3484
|
}
|
|
3464
3485
|
function buildPayload(opts) {
|
|
@@ -3566,7 +3587,7 @@ var API_BASE = "https://api.getpeppr.dev/v1";
|
|
|
3566
3587
|
var LOCAL_BASE = "http://localhost:3001/api/v1";
|
|
3567
3588
|
var DASHBOARD_BASE = "https://console.getpeppr.dev/invoices";
|
|
3568
3589
|
function registerSendCommand(program2) {
|
|
3569
|
-
program2.command("send").description("Send an invoice to the Peppol network via getpeppr API").argument("[file]", "optional path to invoice JSON (mutex with --to/--amount/...)").option("--prod", "target production (live keys + confirmation)").option("--local", "target localhost:3001 dev server").option("--key <key>", "override API key \u2014 for CI/scripted use only; visible in `ps` and shell history. Prefer GETPEPPR_API_KEY env var.").option("--to <peppol-id>", "recipient peppol id (e.g.,
|
|
3590
|
+
program2.command("send").description("Send an invoice to the Peppol network via getpeppr API").argument("[file]", "optional path to invoice JSON (mutex with --to/--amount/...)").option("--prod", "target production (live keys + confirmation)").option("--local", "target localhost:3001 dev server").option("--key <key>", "override API key \u2014 for CI/scripted use only; visible in `ps` and shell history. Prefer GETPEPPR_API_KEY env var.").option("--to <peppol-id>", "recipient peppol id (e.g., 9925:BE0314595348)").option("--country <iso>", "recipient ISO 3166-1 alpha-2 country override (e.g., BE)").option("--amount <number>", "line amount in major currency units (decimal allowed)").option("--currency <iso>", "ISO 4217 currency (default EUR)").option("--desc <text>", "line description").option("--attachment", "attach the test PDF").option("--watch", "poll status until delivered (60s timeout)").option("-y, --yes", "skip --prod confirmation prompt").option("--no-validate", "skip pre-validation locally").option("--json", "output JSON").option("--quiet", "exit code only, no output").action(async (file, flags) => {
|
|
3570
3591
|
let auth;
|
|
3571
3592
|
try {
|
|
3572
3593
|
auth = resolveApiKey({
|
|
@@ -3583,6 +3604,7 @@ function registerSendCommand(program2) {
|
|
|
3583
3604
|
}
|
|
3584
3605
|
const overrides = {
|
|
3585
3606
|
to: flags.to,
|
|
3607
|
+
country: flags.country,
|
|
3586
3608
|
amount: flags.amount != null ? Number(flags.amount) : void 0,
|
|
3587
3609
|
currency: flags.currency,
|
|
3588
3610
|
description: flags.desc,
|