@getpeppr/cli 0.4.3 → 0.4.5
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 +75 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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:0685660237",
|
|
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:0685660237" 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:0685660237"'));
|
|
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.5.
|
|
1062
|
+
var SDK_VERSION = "1.5.2";
|
|
1063
1063
|
|
|
1064
1064
|
// ../sdk/dist/core/client.js
|
|
1065
1065
|
function findHeaderCaseInsensitive(headers, name) {
|
|
@@ -1306,7 +1306,8 @@ var GetpepprAdapter = class {
|
|
|
1306
1306
|
return parseSendResult(result);
|
|
1307
1307
|
}
|
|
1308
1308
|
async lookupDirectory(scheme, id) {
|
|
1309
|
-
|
|
1309
|
+
const result = await this.request("GET", `/directory/${scheme}/${id}`);
|
|
1310
|
+
return parseDirectoryEntry(result);
|
|
1310
1311
|
}
|
|
1311
1312
|
async searchDirectory(params) {
|
|
1312
1313
|
const query = new URLSearchParams(params).toString();
|
|
@@ -1595,6 +1596,40 @@ function parseSendResult(result) {
|
|
|
1595
1596
|
warnings: Array.isArray(result.warnings) ? result.warnings : void 0
|
|
1596
1597
|
};
|
|
1597
1598
|
}
|
|
1599
|
+
function parseDirectoryEntry(result) {
|
|
1600
|
+
const participant = isRecord(result.participant) ? result.participant : result;
|
|
1601
|
+
const scheme = participant.scheme == null ? void 0 : String(participant.scheme);
|
|
1602
|
+
const id = participant.id == null ? void 0 : String(participant.id);
|
|
1603
|
+
const peppolId = participant.peppolId == null ? formatPeppolId(scheme, id) : String(participant.peppolId);
|
|
1604
|
+
return {
|
|
1605
|
+
name: String(participant.name ?? ""),
|
|
1606
|
+
peppolId,
|
|
1607
|
+
country: String(participant.country ?? ""),
|
|
1608
|
+
capabilities: Array.isArray(participant.capabilities) ? participant.capabilities.map(String) : [],
|
|
1609
|
+
registrationDate: participant.registrationDate == null ? void 0 : String(participant.registrationDate),
|
|
1610
|
+
vatNumber: participant.vatNumber == null ? void 0 : String(participant.vatNumber),
|
|
1611
|
+
additionalIds: Array.isArray(participant.additionalIds) ? participant.additionalIds.filter(isRecord).map((entry) => ({
|
|
1612
|
+
scheme: String(entry.scheme ?? ""),
|
|
1613
|
+
value: String(entry.value ?? "")
|
|
1614
|
+
})) : void 0,
|
|
1615
|
+
contactInfo: isRecord(participant.contactInfo) ? {
|
|
1616
|
+
name: participant.contactInfo.name == null ? void 0 : String(participant.contactInfo.name),
|
|
1617
|
+
email: participant.contactInfo.email == null ? void 0 : String(participant.contactInfo.email),
|
|
1618
|
+
phone: participant.contactInfo.phone == null ? void 0 : String(participant.contactInfo.phone)
|
|
1619
|
+
} : void 0,
|
|
1620
|
+
website: participant.website == null ? void 0 : String(participant.website)
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
function formatPeppolId(scheme, id) {
|
|
1624
|
+
if (!id)
|
|
1625
|
+
return scheme ? `${scheme}:` : "";
|
|
1626
|
+
if (id.includes(":"))
|
|
1627
|
+
return id;
|
|
1628
|
+
return scheme ? `${scheme}:${id}` : id;
|
|
1629
|
+
}
|
|
1630
|
+
function isRecord(value) {
|
|
1631
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1632
|
+
}
|
|
1598
1633
|
function parseContact(raw) {
|
|
1599
1634
|
const contact = {
|
|
1600
1635
|
id: String(raw.id ?? ""),
|
|
@@ -1819,8 +1854,8 @@ ${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (
|
|
|
1819
1854
|
* ```ts
|
|
1820
1855
|
* const result = await peppol.invoices.send({
|
|
1821
1856
|
* number: "INV-001",
|
|
1822
|
-
* from: { name: "My Company", peppolId: "0208:
|
|
1823
|
-
* to: { name: "Client Co", peppolId: "0208:
|
|
1857
|
+
* from: { name: "My Company", peppolId: "0208:0685660237", country: "BE" },
|
|
1858
|
+
* to: { name: "Client Co", peppolId: "0208:0685660237", country: "BE" },
|
|
1824
1859
|
* lines: [
|
|
1825
1860
|
* { description: "Consulting", quantity: 10, unitPrice: 150, vatRate: 21 }
|
|
1826
1861
|
* ]
|
|
@@ -1882,7 +1917,7 @@ ${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (
|
|
|
1882
1917
|
* ```ts
|
|
1883
1918
|
* const result = await peppol.invoices.validateServer({
|
|
1884
1919
|
* number: "INV-001",
|
|
1885
|
-
* to: { name: "Acme", peppolId: "0208:
|
|
1920
|
+
* to: { name: "Acme", peppolId: "0208:0685660237", country: "BE" },
|
|
1886
1921
|
* lines: [{ description: "Item", quantity: 1, unitPrice: 100, vatRate: 21 }]
|
|
1887
1922
|
* });
|
|
1888
1923
|
* console.log(result.valid, result.schematron.errors);
|
|
@@ -2079,14 +2114,14 @@ var DirectoryOperations = class {
|
|
|
2079
2114
|
*
|
|
2080
2115
|
* @example
|
|
2081
2116
|
* ```ts
|
|
2082
|
-
* const entry = await peppol.directory.lookup("0208:
|
|
2117
|
+
* const entry = await peppol.directory.lookup("0208:0685660237");
|
|
2083
2118
|
* console.log(entry.name, entry.capabilities);
|
|
2084
2119
|
* ```
|
|
2085
2120
|
*/
|
|
2086
2121
|
async lookup(peppolId) {
|
|
2087
2122
|
const colonIndex = peppolId.indexOf(":");
|
|
2088
2123
|
if (colonIndex === -1) {
|
|
2089
|
-
throw new PeppolError('Invalid Peppol ID format. Expected "scheme:id" (e.g., "0208:
|
|
2124
|
+
throw new PeppolError('Invalid Peppol ID format. Expected "scheme:id" (e.g., "0208:0685660237")');
|
|
2090
2125
|
}
|
|
2091
2126
|
const scheme = peppolId.slice(0, colonIndex);
|
|
2092
2127
|
const id = peppolId.slice(colonIndex + 1);
|
|
@@ -2131,7 +2166,7 @@ var DirectoryOperations = class {
|
|
|
2131
2166
|
*
|
|
2132
2167
|
* @example
|
|
2133
2168
|
* ```ts
|
|
2134
|
-
* const result = await peppol.directory.searchByVat("
|
|
2169
|
+
* const result = await peppol.directory.searchByVat("BE0685660237");
|
|
2135
2170
|
* ```
|
|
2136
2171
|
*/
|
|
2137
2172
|
async searchByVat(vatNumber) {
|
|
@@ -2207,8 +2242,8 @@ var ContactOperations = class {
|
|
|
2207
2242
|
* @example
|
|
2208
2243
|
* ```ts
|
|
2209
2244
|
* const contact = await peppol.contacts.create({
|
|
2210
|
-
* name: "
|
|
2211
|
-
* peppolId: "0208:
|
|
2245
|
+
* name: "ACMEDIA",
|
|
2246
|
+
* peppolId: "0208:0685660237",
|
|
2212
2247
|
* country: "BE",
|
|
2213
2248
|
* isClient: true,
|
|
2214
2249
|
* });
|
|
@@ -2789,7 +2824,7 @@ var INVOICE_TEMPLATE = {
|
|
|
2789
2824
|
buyerReference: "PO-2026-042",
|
|
2790
2825
|
from: {
|
|
2791
2826
|
name: "Dupont & Fils SPRL",
|
|
2792
|
-
peppolId: "0208:
|
|
2827
|
+
peppolId: "0208:0685660237",
|
|
2793
2828
|
street: "Avenue Louise 54",
|
|
2794
2829
|
city: "Bruxelles",
|
|
2795
2830
|
postalCode: "1050",
|
|
@@ -2831,7 +2866,7 @@ var CREDIT_NOTE_TEMPLATE = {
|
|
|
2831
2866
|
invoiceReference: "INV-2026-001",
|
|
2832
2867
|
from: {
|
|
2833
2868
|
name: "Dupont & Fils SPRL",
|
|
2834
|
-
peppolId: "0208:
|
|
2869
|
+
peppolId: "0208:0685660237",
|
|
2835
2870
|
street: "Avenue Louise 54",
|
|
2836
2871
|
city: "Bruxelles",
|
|
2837
2872
|
postalCode: "1050",
|
|
@@ -2995,7 +3030,7 @@ function parseMatch(raw) {
|
|
|
2995
3030
|
};
|
|
2996
3031
|
}
|
|
2997
3032
|
async function lookupParticipant(scheme, id) {
|
|
2998
|
-
const participantParam = `iso6523-actorid-upis::${scheme}:${id}`;
|
|
3033
|
+
const participantParam = `iso6523-actorid-upis::${scheme}:${normalizeParticipantIdentifier(scheme, id)}`;
|
|
2999
3034
|
const url = `${BASE_URL}?participant=${encodeURIComponent(participantParam)}`;
|
|
3000
3035
|
const response = await fetch(url, {
|
|
3001
3036
|
signal: AbortSignal.timeout(15e3),
|
|
@@ -3013,6 +3048,12 @@ async function lookupParticipant(scheme, id) {
|
|
|
3013
3048
|
}
|
|
3014
3049
|
return parseMatch(data.matches[0]);
|
|
3015
3050
|
}
|
|
3051
|
+
function normalizeParticipantIdentifier(scheme, id) {
|
|
3052
|
+
if (scheme === "0208") {
|
|
3053
|
+
return id.replace(/^BE(?=(?:0|1)\d{9}$)/i, "");
|
|
3054
|
+
}
|
|
3055
|
+
return id;
|
|
3056
|
+
}
|
|
3016
3057
|
async function searchParticipants(opts) {
|
|
3017
3058
|
const params = new URLSearchParams();
|
|
3018
3059
|
if (opts.name) params.set("name", opts.name);
|
|
@@ -3141,7 +3182,7 @@ function validatePeppolId(raw) {
|
|
|
3141
3182
|
if (colonIndex === -1) {
|
|
3142
3183
|
return {
|
|
3143
3184
|
ok: false,
|
|
3144
|
-
error: `Invalid Peppol ID format: "${raw}". Expected format: scheme:id (e.g. 0208:
|
|
3185
|
+
error: `Invalid Peppol ID format: "${raw}". Expected format: scheme:id (e.g. 0208:0685660237)`
|
|
3145
3186
|
};
|
|
3146
3187
|
}
|
|
3147
3188
|
const scheme = raw.slice(0, colonIndex);
|
|
@@ -3396,6 +3437,20 @@ startxref
|
|
|
3396
3437
|
190
|
|
3397
3438
|
%%EOF`;
|
|
3398
3439
|
var MINIMAL_TEST_PDF_BASE64 = Buffer.from(MINIMAL_PDF).toString("base64");
|
|
3440
|
+
var SCHEME_COUNTRY_DEFAULTS = {
|
|
3441
|
+
"0009": "FR",
|
|
3442
|
+
"0204": "DE",
|
|
3443
|
+
"0208": "BE",
|
|
3444
|
+
"9925": "BE"
|
|
3445
|
+
};
|
|
3446
|
+
function deriveCountryFromPeppolId(peppolId) {
|
|
3447
|
+
const [scheme, identifier = ""] = peppolId.split(":");
|
|
3448
|
+
const alphaPrefix = identifier.slice(0, 2);
|
|
3449
|
+
if (/^[A-Za-z]{2}$/.test(alphaPrefix)) {
|
|
3450
|
+
return alphaPrefix.toUpperCase();
|
|
3451
|
+
}
|
|
3452
|
+
return SCHEME_COUNTRY_DEFAULTS[scheme] ?? "BE";
|
|
3453
|
+
}
|
|
3399
3454
|
function buildDefaultSendPayload(overrides = {}) {
|
|
3400
3455
|
const today = /* @__PURE__ */ new Date();
|
|
3401
3456
|
const due = new Date(today.getTime() + 30 * 864e5);
|
|
@@ -3407,7 +3462,7 @@ function buildDefaultSendPayload(overrides = {}) {
|
|
|
3407
3462
|
const description = overrides.description ?? "Test service from getpeppr";
|
|
3408
3463
|
const randomSuffix = Math.floor(Math.random() * 65536).toString(16).toUpperCase().padStart(4, "0");
|
|
3409
3464
|
const number = `TEST-${Date.now().toString(36).toUpperCase()}-${randomSuffix}`;
|
|
3410
|
-
const country =
|
|
3465
|
+
const country = overrides.country != null ? overrides.country.toUpperCase() : deriveCountryFromPeppolId(peppolId);
|
|
3411
3466
|
const payload = {
|
|
3412
3467
|
number,
|
|
3413
3468
|
date: isoToday,
|
|
@@ -3459,7 +3514,7 @@ var MutexError = class extends Error {
|
|
|
3459
3514
|
function hasOverrides(o) {
|
|
3460
3515
|
if (!o) return false;
|
|
3461
3516
|
return Boolean(
|
|
3462
|
-
o.to != null && o.to !== "" || o.amount != null || o.currency || o.description || o.attachment === true
|
|
3517
|
+
o.to != null && o.to !== "" || o.country != null && o.country !== "" || o.amount != null || o.currency || o.description || o.attachment === true
|
|
3463
3518
|
);
|
|
3464
3519
|
}
|
|
3465
3520
|
function buildPayload(opts) {
|
|
@@ -3567,7 +3622,7 @@ var API_BASE = "https://api.getpeppr.dev/v1";
|
|
|
3567
3622
|
var LOCAL_BASE = "http://localhost:3001/api/v1";
|
|
3568
3623
|
var DASHBOARD_BASE = "https://console.getpeppr.dev/invoices";
|
|
3569
3624
|
function registerSendCommand(program2) {
|
|
3570
|
-
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.,
|
|
3625
|
+
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) => {
|
|
3571
3626
|
let auth;
|
|
3572
3627
|
try {
|
|
3573
3628
|
auth = resolveApiKey({
|
|
@@ -3584,6 +3639,7 @@ function registerSendCommand(program2) {
|
|
|
3584
3639
|
}
|
|
3585
3640
|
const overrides = {
|
|
3586
3641
|
to: flags.to,
|
|
3642
|
+
country: flags.country,
|
|
3587
3643
|
amount: flags.amount != null ? Number(flags.amount) : void 0,
|
|
3588
3644
|
currency: flags.currency,
|
|
3589
3645
|
description: flags.desc,
|