@getpeppr/cli 0.2.0 → 0.2.2
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 +94 -40
- package/dist/index.js +16 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @getpeppr/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Developer toolkit for Peppol e-invoicing. Scaffold invoices, validate against Peppol BIS 3.0, convert to UBL XML, and look up participants in the Peppol Directory — all from the command line.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,12 +10,27 @@ npx @getpeppr/cli validate invoice.json
|
|
|
10
10
|
|
|
11
11
|
# Or install globally
|
|
12
12
|
npm install -g @getpeppr/cli
|
|
13
|
-
getpeppr
|
|
13
|
+
getpeppr --help
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Commands
|
|
17
|
+
|
|
18
|
+
### `getpeppr init` — Scaffold an invoice
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Generate a starter JSON file with all required fields pre-filled:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
getpeppr init # creates invoice.json
|
|
24
|
+
getpeppr init my-invoice.json # custom filename
|
|
25
|
+
getpeppr init --credit-note # credit note template
|
|
26
|
+
getpeppr init --force # overwrite existing file
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The generated template includes a Belgian seller, a German buyer, and two invoice lines — ready to edit and validate.
|
|
30
|
+
|
|
31
|
+
### `getpeppr validate` — Validate an invoice
|
|
32
|
+
|
|
33
|
+
Run offline validation against Peppol BIS 3.0 business rules:
|
|
19
34
|
|
|
20
35
|
```bash
|
|
21
36
|
getpeppr validate invoice.json
|
|
@@ -39,47 +54,69 @@ Validating: invoice.json
|
|
|
39
54
|
✓ Invoice is valid (1 warning)
|
|
40
55
|
```
|
|
41
56
|
|
|
42
|
-
### Flags
|
|
43
|
-
|
|
44
57
|
| Flag | Description |
|
|
45
58
|
|------|-------------|
|
|
46
59
|
| `--json` | Machine-readable JSON output |
|
|
47
60
|
| `--quiet` | Exit code only, no output |
|
|
48
|
-
| `--version` | Show version number |
|
|
49
|
-
| `--help` | Show help |
|
|
50
61
|
|
|
51
|
-
###
|
|
62
|
+
### `getpeppr convert` — Convert to UBL XML
|
|
52
63
|
|
|
53
|
-
|
|
54
|
-
|------|---------|
|
|
55
|
-
| `0` | Invoice is valid (may have warnings) |
|
|
56
|
-
| `1` | Invoice has errors — non-compliant |
|
|
57
|
-
| `2` | File not found or invalid JSON |
|
|
58
|
-
|
|
59
|
-
### JSON output
|
|
64
|
+
Convert a getpeppr JSON invoice to Peppol BIS 3.0 UBL 2.1 XML:
|
|
60
65
|
|
|
61
66
|
```bash
|
|
62
|
-
getpeppr
|
|
67
|
+
getpeppr convert invoice.json # XML to stdout
|
|
68
|
+
getpeppr convert invoice.json -o invoice.xml # write to file
|
|
69
|
+
getpeppr convert invoice.json --validate # validate first, convert only if valid
|
|
63
70
|
```
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
Automatically detects credit notes (`"isCreditNote": true`) and produces the correct UBL CreditNote document.
|
|
66
73
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
| Flag | Description |
|
|
75
|
+
|------|-------------|
|
|
76
|
+
| `-o, --output <file>` | Write XML to file instead of stdout |
|
|
77
|
+
| `--validate` | Validate before converting (errors block conversion) |
|
|
78
|
+
|
|
79
|
+
### `getpeppr lookup` — Peppol Directory search
|
|
80
|
+
|
|
81
|
+
Look up any participant registered on the Peppol network:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Direct lookup by Peppol ID
|
|
85
|
+
getpeppr lookup 0208:BE0685660237
|
|
86
|
+
|
|
87
|
+
# Search by company name
|
|
88
|
+
getpeppr lookup --name "Dupont"
|
|
89
|
+
|
|
90
|
+
# Filter by country
|
|
91
|
+
getpeppr lookup --name "GmbH" --country DE
|
|
92
|
+
|
|
93
|
+
# JSON output
|
|
94
|
+
getpeppr lookup 0208:BE0685660237 --json
|
|
76
95
|
```
|
|
77
96
|
|
|
78
|
-
|
|
97
|
+
| Flag | Description |
|
|
98
|
+
|------|-------------|
|
|
99
|
+
| `--name <name>` | Search by company name (min 3 characters) |
|
|
100
|
+
| `--country <code>` | Filter by ISO 2-letter country code |
|
|
101
|
+
| `--json` | Output results as JSON |
|
|
102
|
+
| `--limit <n>` | Max results for search (default: 10) |
|
|
103
|
+
|
|
104
|
+
## Exit codes
|
|
105
|
+
|
|
106
|
+
| Code | Meaning |
|
|
107
|
+
|------|---------|
|
|
108
|
+
| `0` | Success (valid invoice, participant found, conversion OK) |
|
|
109
|
+
| `1` | Failure (invalid invoice, participant not found) |
|
|
110
|
+
| `2` | Input error (file not found, invalid JSON, bad arguments) |
|
|
111
|
+
|
|
112
|
+
## CI/CD integration
|
|
79
113
|
|
|
80
114
|
```bash
|
|
81
115
|
# Fail pipeline if invoice is invalid
|
|
82
116
|
getpeppr validate invoice.json --quiet || exit 1
|
|
117
|
+
|
|
118
|
+
# Validate + convert in one step
|
|
119
|
+
getpeppr convert invoice.json --validate -o output.xml
|
|
83
120
|
```
|
|
84
121
|
|
|
85
122
|
## What it validates
|
|
@@ -90,7 +127,7 @@ The CLI runs three validation engines from the [@getpeppr/sdk](https://www.npmjs
|
|
|
90
127
|
2. **Business Rules** — Peppol BIS 3.0 / EN 16931 compliance (BR-xx, BR-CO-xx, PEPPOL-xx rules)
|
|
91
128
|
3. **Country Rules** — Belgium (BE), France (FR), Italy (IT), Netherlands (NL), Germany (DE)
|
|
92
129
|
|
|
93
|
-
|
|
130
|
+
Validation runs offline — no API key or network connection required. Only `lookup` needs an internet connection.
|
|
94
131
|
|
|
95
132
|
## Invoice format
|
|
96
133
|
|
|
@@ -99,30 +136,47 @@ The input file must be a JSON object matching the getpeppr `InvoiceInput` type:
|
|
|
99
136
|
```json
|
|
100
137
|
{
|
|
101
138
|
"number": "INV-2026-001",
|
|
102
|
-
"date": "2026-
|
|
103
|
-
"dueDate": "2026-
|
|
139
|
+
"date": "2026-01-15",
|
|
140
|
+
"dueDate": "2026-02-15",
|
|
104
141
|
"currency": "EUR",
|
|
105
|
-
"buyerReference": "PO-
|
|
106
|
-
"
|
|
107
|
-
"name": "
|
|
142
|
+
"buyerReference": "PO-2026-042",
|
|
143
|
+
"from": {
|
|
144
|
+
"name": "Dupont & Fils SPRL",
|
|
108
145
|
"peppolId": "0208:BE0123456789",
|
|
109
|
-
"street": "
|
|
110
|
-
"city": "
|
|
146
|
+
"street": "Avenue Louise 54",
|
|
147
|
+
"city": "Bruxelles",
|
|
111
148
|
"postalCode": "1050",
|
|
112
149
|
"country": "BE"
|
|
113
150
|
},
|
|
151
|
+
"to": {
|
|
152
|
+
"name": "Müller & Partner GmbH",
|
|
153
|
+
"peppolId": "0204:DE987654321",
|
|
154
|
+
"street": "Friedrichstraße 123",
|
|
155
|
+
"city": "Berlin",
|
|
156
|
+
"postalCode": "10117",
|
|
157
|
+
"country": "DE"
|
|
158
|
+
},
|
|
114
159
|
"lines": [
|
|
115
160
|
{
|
|
116
|
-
"description": "
|
|
161
|
+
"description": "Conseil en transformation numérique",
|
|
117
162
|
"quantity": 10,
|
|
118
|
-
"unitPrice":
|
|
163
|
+
"unitPrice": 950,
|
|
119
164
|
"vatRate": 21
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"description": "Software license — annual subscription",
|
|
168
|
+
"quantity": 1,
|
|
169
|
+
"unitPrice": 2400,
|
|
170
|
+
"vatRate": 0,
|
|
171
|
+
"vatCategory": "AE"
|
|
120
172
|
}
|
|
121
|
-
]
|
|
173
|
+
],
|
|
174
|
+
"paymentTerms": "Net 30 days",
|
|
175
|
+
"paymentReference": "+++000/0000/00097+++"
|
|
122
176
|
}
|
|
123
177
|
```
|
|
124
178
|
|
|
125
|
-
See the [full type reference](https://getpeppr.dev/docs/types/) for all available fields.
|
|
179
|
+
This is the exact template generated by `getpeppr init`. See the [full type reference](https://getpeppr.dev/docs/types/) for all available fields.
|
|
126
180
|
|
|
127
181
|
## Ready to send?
|
|
128
182
|
|
package/dist/index.js
CHANGED
|
@@ -175,12 +175,12 @@ var INVOICE_TEMPLATE = {
|
|
|
175
175
|
currency: "EUR",
|
|
176
176
|
buyerReference: "PO-2026-042",
|
|
177
177
|
from: {
|
|
178
|
-
name: "
|
|
179
|
-
peppolId: "
|
|
180
|
-
street: "
|
|
181
|
-
city: "
|
|
182
|
-
postalCode: "
|
|
183
|
-
country: "
|
|
178
|
+
name: "Dupont & Fils SPRL",
|
|
179
|
+
peppolId: "0208:BE0123456789",
|
|
180
|
+
street: "Avenue Louise 54",
|
|
181
|
+
city: "Bruxelles",
|
|
182
|
+
postalCode: "1050",
|
|
183
|
+
country: "BE"
|
|
184
184
|
},
|
|
185
185
|
to: {
|
|
186
186
|
name: "M\xFCller & Partner GmbH",
|
|
@@ -195,7 +195,7 @@ var INVOICE_TEMPLATE = {
|
|
|
195
195
|
description: "Conseil en transformation num\xE9rique",
|
|
196
196
|
quantity: 10,
|
|
197
197
|
unitPrice: 950,
|
|
198
|
-
vatRate:
|
|
198
|
+
vatRate: 21
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
description: "Software license \u2014 annual subscription",
|
|
@@ -205,7 +205,8 @@ var INVOICE_TEMPLATE = {
|
|
|
205
205
|
vatCategory: "AE"
|
|
206
206
|
}
|
|
207
207
|
],
|
|
208
|
-
paymentTerms: "Net 30 days"
|
|
208
|
+
paymentTerms: "Net 30 days",
|
|
209
|
+
paymentReference: "+++000/0000/00097+++"
|
|
209
210
|
};
|
|
210
211
|
|
|
211
212
|
// src/templates/credit-note.ts
|
|
@@ -216,12 +217,12 @@ var CREDIT_NOTE_TEMPLATE = {
|
|
|
216
217
|
isCreditNote: true,
|
|
217
218
|
invoiceReference: "INV-2026-001",
|
|
218
219
|
from: {
|
|
219
|
-
name: "
|
|
220
|
-
peppolId: "
|
|
221
|
-
street: "
|
|
222
|
-
city: "
|
|
223
|
-
postalCode: "
|
|
224
|
-
country: "
|
|
220
|
+
name: "Dupont & Fils SPRL",
|
|
221
|
+
peppolId: "0208:BE0123456789",
|
|
222
|
+
street: "Avenue Louise 54",
|
|
223
|
+
city: "Bruxelles",
|
|
224
|
+
postalCode: "1050",
|
|
225
|
+
country: "BE"
|
|
225
226
|
},
|
|
226
227
|
to: {
|
|
227
228
|
name: "M\xFCller & Partner GmbH",
|
|
@@ -236,7 +237,7 @@ var CREDIT_NOTE_TEMPLATE = {
|
|
|
236
237
|
description: "Avoir partiel \u2014 Conseil en transformation num\xE9rique",
|
|
237
238
|
quantity: 2,
|
|
238
239
|
unitPrice: 950,
|
|
239
|
-
vatRate:
|
|
240
|
+
vatRate: 21
|
|
240
241
|
}
|
|
241
242
|
],
|
|
242
243
|
note: "Avoir pour prestations non r\xE9alis\xE9es \u2014 r\xE9f. INV-2026-001"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/file.ts","../src/formatters/validation.ts","../src/commands/validate.ts","../src/commands/init.ts","../src/templates/invoice.ts","../src/templates/credit-note.ts","../src/commands/convert.ts","../src/commands/lookup.ts","../src/lib/peppol-directory.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport { registerValidateCommand } from \"./commands/validate.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerConvertCommand } from \"./commands/convert.js\";\nimport { registerLookupCommand } from \"./commands/lookup.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"getpeppr\")\n .description(\"CLI tool for Peppol e-invoice validation and development\")\n .version(version);\n\nregisterValidateCommand(program);\nregisterInitCommand(program);\nregisterConvertCommand(program);\nregisterLookupCommand(program);\n\nprogram.parse();\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport type FileReadResult =\n | { ok: true; data: unknown }\n | { ok: false; error: string };\n\nexport function readJsonFile(filePath: string): FileReadResult {\n const resolved = resolve(filePath);\n\n if (!existsSync(resolved)) {\n return { ok: false, error: `Error: file not found — ${resolved}` };\n }\n\n let content: string;\n try {\n content = readFileSync(resolved, \"utf-8\");\n } catch {\n return { ok: false, error: `Error: could not read file — ${resolved}` };\n }\n\n try {\n const data: unknown = JSON.parse(content);\n return { ok: true, data };\n } catch {\n return { ok: false, error: `Error: invalid JSON in file — ${resolved}` };\n }\n}\n","import pc from \"picocolors\";\nimport type { MergedValidationResult } from \"../commands/validate.js\";\nimport type { ValidationError, ValidationWarning, SchematronViolation } from \"@getpeppr/sdk\";\n\nfunction sectionHeader(title: string): string {\n const pad = 45 - title.length - 4;\n return pc.dim(`── ${title} ${\"─\".repeat(Math.max(pad, 3))}`);\n}\n\nfunction formatError(item: ValidationError | SchematronViolation): string {\n const ruleId = \"ruleId\" in item && item.ruleId ? pc.dim(` (${item.ruleId})`) : \"\";\n const field = \"field\" in item && item.field ? `${item.field} — ` : \"\";\n return ` ${pc.red(\"✗\")} ${field}${item.message}${ruleId}`;\n}\n\nfunction formatWarning(item: ValidationWarning | SchematronViolation): string {\n const ruleId = \"ruleId\" in item && item.ruleId ? pc.dim(` (${item.ruleId})`) : \"\";\n const field = \"field\" in item && item.field ? `${item.field} — ` : \"\";\n return ` ${pc.yellow(\"⚠\")} ${field}${item.message}${ruleId}`;\n}\n\nfunction formatSection(\n title: string,\n errors: (ValidationError | SchematronViolation)[],\n warnings: (ValidationWarning | SchematronViolation)[],\n): string {\n const lines: string[] = [sectionHeader(title)];\n\n if (errors.length === 0 && warnings.length === 0) {\n lines.push(` ${pc.green(\"✓\")} All rules passed`);\n return lines.join(\"\\n\");\n }\n\n if (errors.length === 0) {\n lines.push(` ${pc.green(\"✓\")} No errors`);\n }\n\n for (const err of errors) {\n lines.push(formatError(err));\n }\n\n for (const warn of warnings) {\n lines.push(formatWarning(warn));\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function formatValidationResult(\n filename: string,\n result: MergedValidationResult,\n): string {\n const lines: string[] = [];\n\n lines.push(`\\nValidating: ${pc.bold(filename)}\\n`);\n\n lines.push(\n formatSection(\n \"Structure\",\n result.structure.errors,\n result.structure.warnings,\n ),\n );\n lines.push(\"\");\n\n lines.push(\n formatSection(\n \"Business Rules (Peppol BIS 3.0)\",\n result.schematron.errors,\n result.schematron.warnings,\n ),\n );\n lines.push(\"\");\n\n lines.push(\n formatSection(\n \"Country Rules\",\n result.countryRules.errors,\n result.countryRules.warnings,\n ),\n );\n lines.push(\"\");\n\n // Summary\n lines.push(sectionHeader(\"Summary\"));\n const { totalErrors, totalWarnings, valid } = result;\n\n if (valid && totalWarnings === 0) {\n lines.push(` ${pc.green(pc.bold(\"✓ Invoice is valid\"))}`);\n } else if (valid) {\n lines.push(\n ` ${pc.green(pc.bold(\"✓ Invoice is valid\"))} ${pc.dim(`(${totalWarnings} warning${totalWarnings === 1 ? \"\" : \"s\"})`)}`,\n );\n } else {\n const parts: string[] = [];\n parts.push(`${totalErrors} error${totalErrors === 1 ? \"\" : \"s\"}`);\n if (totalWarnings > 0) {\n parts.push(`${totalWarnings} warning${totalWarnings === 1 ? \"\" : \"s\"}`);\n }\n lines.push(\n ` ${pc.red(pc.bold(`✗ ${parts.join(\", \")}`))} — invoice non-compliant`,\n );\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n","import type { Command } from \"commander\";\nimport { readJsonFile } from \"../utils/file.js\";\nimport { formatValidationResult } from \"../formatters/validation.js\";\nimport {\n validateInvoice,\n validateSchematron,\n validateCountryRules,\n type InvoiceInput,\n type ValidationError,\n type ValidationWarning,\n type SchematronViolation,\n} from \"@getpeppr/sdk\";\n\nexport interface MergedValidationResult {\n structure: {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n };\n schematron: {\n errors: SchematronViolation[];\n warnings: SchematronViolation[];\n };\n countryRules: {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n };\n totalErrors: number;\n totalWarnings: number;\n valid: boolean;\n}\n\nexport function runValidation(input: InvoiceInput): MergedValidationResult {\n const structure = validateInvoice(input);\n const schematron = validateSchematron(input);\n const countryRules = validateCountryRules(input);\n\n const totalErrors =\n structure.errors.length +\n schematron.errors.length +\n countryRules.errors.length;\n\n const totalWarnings =\n structure.warnings.length +\n schematron.warnings.length +\n countryRules.warnings.length;\n\n return {\n structure: { errors: structure.errors, warnings: structure.warnings },\n schematron: { errors: schematron.errors, warnings: schematron.warnings },\n countryRules: {\n errors: countryRules.errors,\n warnings: countryRules.warnings,\n },\n totalErrors,\n totalWarnings,\n valid: totalErrors === 0,\n };\n}\n\nexport function registerValidateCommand(program: Command): void {\n program\n .command(\"validate\")\n .description(\"Validate a Peppol invoice JSON file\")\n .argument(\"<file>\", \"path to invoice JSON file\")\n .option(\"--json\", \"output results as JSON\")\n .option(\"--quiet\", \"exit code only, no output\")\n .action(async (file: string, options: { json?: boolean; quiet?: boolean }) => {\n // 1. Read and parse the JSON file\n // Fatal errors always go to stderr regardless of --quiet (UNIX convention)\n const parseResult = readJsonFile(file);\n if (!parseResult.ok) {\n process.stderr.write(parseResult.error + \"\\n\");\n process.exit(2);\n }\n\n if (\n typeof parseResult.data !== \"object\" ||\n parseResult.data === null ||\n Array.isArray(parseResult.data)\n ) {\n process.stderr.write(\n \"Error: JSON file must contain an object, not an array or primitive\\n\",\n );\n process.exit(2);\n }\n\n const input = parseResult.data as InvoiceInput;\n\n // 2. Run all 3 validators\n const result = runValidation(input);\n\n // 3. Output\n if (options.quiet) {\n process.exit(result.valid ? 0 : 1);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n process.exit(result.valid ? 0 : 1);\n }\n\n // 4. Formatted output\n const output = formatValidationResult(file, result);\n console.log(output);\n process.exit(result.valid ? 0 : 1);\n });\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { INVOICE_TEMPLATE } from \"../templates/invoice.js\";\nimport { CREDIT_NOTE_TEMPLATE } from \"../templates/credit-note.js\";\n\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .description(\"Scaffold a starter invoice JSON file\")\n .argument(\"[filename]\", \"output filename\", \"invoice.json\")\n .option(\"--credit-note\", \"generate a credit note template instead\")\n .option(\"--force\", \"overwrite existing file\")\n .action(\n (\n filename: string,\n options: { creditNote?: boolean; force?: boolean },\n ) => {\n const resolved = resolve(filename);\n\n if (existsSync(resolved) && !options.force) {\n console.error(\n `Error: ${filename} already exists. Use --force to overwrite.`,\n );\n process.exit(2);\n }\n\n const template = options.creditNote\n ? CREDIT_NOTE_TEMPLATE\n : INVOICE_TEMPLATE;\n\n try {\n writeFileSync(\n resolved,\n JSON.stringify(template, null, 2) + \"\\n\",\n \"utf-8\",\n );\n } catch {\n console.error(`Error: could not write file — ${resolved}`);\n process.exit(2);\n }\n\n console.error(`${pc.green(\"\\u2713\")} Created ${filename}\n\n Next steps:\n 1. Edit the file with your invoice data\n 2. Validate: getpeppr validate ${filename}\n 3. Convert to XML: getpeppr convert ${filename}`);\n\n process.exit(0);\n },\n );\n}\n","import type { InvoiceInput } from \"@getpeppr/sdk\";\n\nexport const INVOICE_TEMPLATE: InvoiceInput = {\n number: \"INV-2026-001\",\n date: \"2026-01-15\",\n dueDate: \"2026-02-15\",\n currency: \"EUR\",\n buyerReference: \"PO-2026-042\",\n from: {\n name: \"Soci\\u00e9t\\u00e9 \\u00c9clair SARL\",\n peppolId: \"0009:FR12345678901\",\n street: \"14 Rue de la Paix\",\n city: \"Paris\",\n postalCode: \"75002\",\n country: \"FR\",\n },\n to: {\n name: \"M\\u00fcller & Partner GmbH\",\n peppolId: \"0204:DE987654321\",\n street: \"Friedrichstra\\u00dfe 123\",\n city: \"Berlin\",\n postalCode: \"10117\",\n country: \"DE\",\n },\n lines: [\n {\n description: \"Conseil en transformation num\\u00e9rique\",\n quantity: 10,\n unitPrice: 950,\n vatRate: 20,\n },\n {\n description: \"Software license \\u2014 annual subscription\",\n quantity: 1,\n unitPrice: 2400,\n vatRate: 0,\n vatCategory: \"AE\",\n },\n ],\n paymentTerms: \"Net 30 days\",\n};\n","import type { InvoiceInput } from \"@getpeppr/sdk\";\n\nexport const CREDIT_NOTE_TEMPLATE: InvoiceInput = {\n number: \"CN-2026-001\",\n date: \"2026-02-01\",\n currency: \"EUR\",\n isCreditNote: true,\n invoiceReference: \"INV-2026-001\",\n from: {\n name: \"Soci\\u00e9t\\u00e9 \\u00c9clair SARL\",\n peppolId: \"0009:FR12345678901\",\n street: \"14 Rue de la Paix\",\n city: \"Paris\",\n postalCode: \"75002\",\n country: \"FR\",\n },\n to: {\n name: \"M\\u00fcller & Partner GmbH\",\n peppolId: \"0204:DE987654321\",\n street: \"Friedrichstra\\u00dfe 123\",\n city: \"Berlin\",\n postalCode: \"10117\",\n country: \"DE\",\n },\n lines: [\n {\n description: \"Avoir partiel \\u2014 Conseil en transformation num\\u00e9rique\",\n quantity: 2,\n unitPrice: 950,\n vatRate: 20,\n },\n ],\n note: \"Avoir pour prestations non r\\u00e9alis\\u00e9es \\u2014 r\\u00e9f. INV-2026-001\",\n};\n","import { writeFileSync } from \"node:fs\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { readJsonFile } from \"../utils/file.js\";\nimport { runValidation } from \"./validate.js\";\nimport { formatValidationResult } from \"../formatters/validation.js\";\nimport {\n buildInvoiceXml,\n buildCreditNoteXml,\n type InvoiceInput,\n type CreditNoteInput,\n} from \"@getpeppr/sdk\";\n\nexport function registerConvertCommand(program: Command): void {\n program\n .command(\"convert\")\n .description(\n \"Convert a getpeppr JSON invoice to Peppol BIS 3.0 UBL XML\",\n )\n .argument(\"<file>\", \"path to invoice JSON file\")\n .option(\"-o, --output <file>\", \"write XML to file instead of stdout\")\n .option(\"--validate\", \"validate the invoice before converting\")\n .action(\n async (\n file: string,\n options: { output?: string; validate?: boolean },\n ) => {\n // 1. Read and parse the JSON file\n const parseResult = readJsonFile(file);\n if (!parseResult.ok) {\n process.stderr.write(parseResult.error + \"\\n\");\n process.exit(2);\n }\n\n if (\n typeof parseResult.data !== \"object\" ||\n parseResult.data === null ||\n Array.isArray(parseResult.data)\n ) {\n process.stderr.write(\n \"Error: JSON file must contain an object, not an array or primitive\\n\",\n );\n process.exit(2);\n }\n\n const input = parseResult.data as InvoiceInput;\n\n // 2. If --validate, run validation first\n if (options.validate) {\n const result = runValidation(input);\n const formatted = formatValidationResult(file, result);\n\n if (!result.valid) {\n // Errors: show on stderr, exit 1, NO XML\n process.stderr.write(formatted + \"\\n\");\n process.exit(1);\n }\n\n if (result.totalWarnings > 0) {\n // Warnings only: show on stderr, continue to conversion\n process.stderr.write(formatted + \"\\n\");\n }\n }\n\n // 3. Detect document type\n const isCreditNote = input.isCreditNote === true;\n\n // 4. Generate XML\n let xml: string;\n try {\n if (isCreditNote) {\n xml = buildCreditNoteXml(input as CreditNoteInput);\n } else {\n xml = buildInvoiceXml(input);\n }\n } catch (err: unknown) {\n const message =\n err instanceof Error ? err.message : \"Unknown error\";\n process.stderr.write(`Error: XML generation failed — ${message}\\n`);\n process.exit(2);\n }\n\n // 5. Clean empty lines from XML\n xml = xml.replace(/^[ \\t]*\\n/gm, \"\");\n\n // 6. Output\n const docType = isCreditNote\n ? \"UBL 2.1 CreditNote\"\n : \"UBL 2.1 Invoice\";\n\n if (options.output) {\n writeFileSync(options.output, xml, \"utf-8\");\n process.stderr.write(\n `${pc.green(\"✓\")} Converted to ${options.output} (${docType})\\n`,\n );\n } else {\n process.stdout.write(xml + \"\\n\");\n }\n },\n );\n}\n","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport {\n lookupParticipant,\n searchParticipants,\n type DirectoryMatch,\n type SearchResult,\n} from \"../lib/peppol-directory.js\";\n\n// ─── Country name helper ──────────────────────────\n\nconst COUNTRY_NAMES: Record<string, string> = {\n AT: \"Austria\",\n BE: \"Belgium\",\n BG: \"Bulgaria\",\n HR: \"Croatia\",\n CY: \"Cyprus\",\n CZ: \"Czechia\",\n DK: \"Denmark\",\n EE: \"Estonia\",\n FI: \"Finland\",\n FR: \"France\",\n DE: \"Germany\",\n GR: \"Greece\",\n HU: \"Hungary\",\n IS: \"Iceland\",\n IE: \"Ireland\",\n IT: \"Italy\",\n LV: \"Latvia\",\n LT: \"Lithuania\",\n LU: \"Luxembourg\",\n MT: \"Malta\",\n NL: \"Netherlands\",\n NO: \"Norway\",\n PL: \"Poland\",\n PT: \"Portugal\",\n RO: \"Romania\",\n SK: \"Slovakia\",\n SI: \"Slovenia\",\n ES: \"Spain\",\n SE: \"Sweden\",\n CH: \"Switzerland\",\n GB: \"United Kingdom\",\n US: \"United States\",\n AU: \"Australia\",\n CA: \"Canada\",\n SG: \"Singapore\",\n JP: \"Japan\",\n NZ: \"New Zealand\",\n};\n\nfunction countryLabel(code: string): string {\n const name = COUNTRY_NAMES[code.toUpperCase()];\n return name ? `${name} (${code})` : code;\n}\n\n// ─── Output formatting ───────────────────────────\n\nfunction formatLookupResult(match: DirectoryMatch): string {\n const lines: string[] = [];\n lines.push(`${pc.green(\"\\u2713\")} ${match.name}`);\n lines.push(` ${pc.dim(\"Peppol ID\")} ${match.peppolId}`);\n lines.push(` ${pc.dim(\"Country\")} ${countryLabel(match.country)}`);\n if (match.registrationDate) {\n lines.push(` ${pc.dim(\"Registered\")} ${match.registrationDate}`);\n }\n if (match.vatNumber) {\n lines.push(` ${pc.dim(\"VAT\")} ${match.vatNumber}`);\n }\n if (match.capabilities.length > 0) {\n lines.push(\n ` ${pc.dim(\"Capabilities\")} ${match.capabilities.join(\", \")}`,\n );\n }\n if (match.contactEmail) {\n lines.push(` ${pc.dim(\"Contact\")} ${match.contactEmail}`);\n }\n if (match.website) {\n lines.push(` ${pc.dim(\"Website\")} ${match.website}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatSearchResults(result: SearchResult): string {\n const lines: string[] = [];\n const plural = result.totalCount === 1 ? \"participant\" : \"participants\";\n lines.push(`Found ${result.totalCount} ${plural}:\\n`);\n\n // Column headers\n const nameW = 26;\n const idW = 23;\n const countryW = 9;\n\n lines.push(\n ` ${\"Name\".padEnd(nameW)}${\"Peppol ID\".padEnd(idW)}${\"Country\".padEnd(countryW)}Capabilities`,\n );\n lines.push(` ${\"─\".repeat(nameW + idW + countryW + 20)}`);\n\n for (const m of result.matches) {\n const name = m.name.length > nameW - 1 ? m.name.slice(0, nameW - 2) + \"…\" : m.name;\n const caps = m.capabilities.join(\", \");\n lines.push(\n ` ${name.padEnd(nameW)}${m.peppolId.padEnd(idW)}${m.country.padEnd(countryW)}${caps}`,\n );\n }\n\n if (result.hasMore) {\n lines.push(\n `\\n ${pc.dim(`Showing ${result.matches.length} of ${result.totalCount} results.`)}`,\n );\n }\n\n return lines.join(\"\\n\");\n}\n\n// ─── Input validation ─────────────────────────────\n\nfunction validatePeppolId(raw: string): {\n ok: true;\n scheme: string;\n id: string;\n} | { ok: false; error: string } {\n const colonIndex = raw.indexOf(\":\");\n if (colonIndex === -1) {\n return {\n ok: false,\n error: `Invalid Peppol ID format: \"${raw}\". Expected format: scheme:id (e.g. 0208:BE0685660237)`,\n };\n }\n\n const scheme = raw.slice(0, colonIndex);\n const id = raw.slice(colonIndex + 1);\n\n if (!/^\\d{4}$/.test(scheme)) {\n return {\n ok: false,\n error: `Invalid scheme \"${scheme}\". Must be exactly 4 digits (e.g. 0208).`,\n };\n }\n\n if (!/^[A-Za-z0-9:.\\-]+$/.test(id)) {\n return {\n ok: false,\n error: `Invalid participant ID \"${id}\". Only letters, digits, colons, dots and hyphens are allowed.`,\n };\n }\n\n return { ok: true, scheme, id };\n}\n\n// ─── Command registration ─────────────────────────\n\nexport function registerLookupCommand(program: Command): void {\n program\n .command(\"lookup\")\n .description(\"Look up a participant in the Peppol Directory\")\n .argument(\"[peppolId]\", \"Peppol participant ID (format: scheme:id)\")\n .option(\"--name <name>\", \"search by company name (min 3 chars)\")\n .option(\"--country <code>\", \"filter by ISO 2-letter country code\")\n .option(\"--json\", \"output results as JSON\")\n .option(\"--limit <n>\", \"max results (default 10)\", \"10\")\n .action(\n async (\n peppolId: string | undefined,\n options: {\n name?: string;\n country?: string;\n json?: boolean;\n limit?: string;\n },\n ) => {\n const isSearch = Boolean(options.name);\n const isLookup = Boolean(peppolId);\n\n // Must have at least one criterion\n if (!isSearch && !isLookup) {\n process.stderr.write(\n \"Provide a Peppol ID or use --name to search.\\n\",\n );\n process.exit(2);\n }\n\n // Validate --country format\n if (options.country) {\n const normalized = options.country.toUpperCase();\n if (!/^[A-Z]{2}$/.test(normalized)) {\n process.stderr.write(\n `Invalid country code \"${options.country}\". Must be 2 letters (e.g. BE, DE, FR).\\n`,\n );\n process.exit(2);\n }\n options.country = normalized;\n }\n\n if (isLookup) {\n await handleLookup(peppolId!, options);\n } else {\n await handleSearch(options);\n }\n },\n );\n}\n\n// ─── Lookup handler ───────────────────────────────\n\nasync function handleLookup(\n peppolId: string,\n options: { json?: boolean },\n): Promise<void> {\n const parsed = validatePeppolId(peppolId);\n if (!parsed.ok) {\n process.stderr.write(parsed.error + \"\\n\");\n process.exit(2);\n }\n\n let result: DirectoryMatch | null;\n\n try {\n result = await lookupParticipant(parsed.scheme, parsed.id);\n } catch {\n process.stderr.write(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.\\n`,\n );\n process.exit(2);\n }\n\n if (!result) {\n if (options.json) {\n console.log(JSON.stringify(null));\n } else {\n process.stderr.write(\n `${pc.red(\"\\u2717\")} Participant not found: ${peppolId}\\n`,\n );\n }\n process.exit(1);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatLookupResult(result));\n }\n process.exit(0);\n}\n\n// ─── Search handler ───────────────────────────────\n\nasync function handleSearch(options: {\n name?: string;\n country?: string;\n json?: boolean;\n limit?: string;\n}): Promise<void> {\n if (options.name && options.name.length < 3) {\n process.stderr.write(\n `Search name must be at least 3 characters. Got: \"${options.name}\"\\n`,\n );\n process.exit(2);\n }\n\n const limit = parseInt(options.limit ?? \"10\", 10);\n\n let result: SearchResult;\n\n try {\n result = await searchParticipants({\n name: options.name,\n country: options.country,\n limit,\n });\n } catch {\n process.stderr.write(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.\\n`,\n );\n process.exit(2);\n }\n\n if (result.matches.length === 0) {\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n process.stderr.write(\"No participants found.\\n\");\n }\n process.exit(1);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatSearchResults(result));\n }\n process.exit(0);\n}\n","const BASE_URL = \"https://directory.peppol.eu/search/1.0/json\";\n\n// ─── Public types ─────────────────────────────────\n\nexport interface DirectoryMatch {\n name: string;\n peppolId: string;\n country: string;\n capabilities: string[];\n registrationDate?: string;\n vatNumber?: string;\n contactEmail?: string;\n website?: string;\n}\n\nexport interface SearchResult {\n matches: DirectoryMatch[];\n totalCount: number;\n hasMore: boolean;\n}\n\n// ─── Response types (Peppol Directory JSON) ───────\n\ninterface DirectoryParticipantID {\n scheme: string;\n value: string;\n}\n\ninterface DirectoryDocType {\n scheme: string;\n value: string;\n}\n\ninterface DirectoryEntity {\n name: Array<{ name: string; language?: string }>;\n countryCode: string;\n geoInfo?: string;\n identifiers?: Array<{ scheme: string; value: string }>;\n websites?: string[];\n contacts?: Array<{ type: string; name?: string; email?: string }>;\n additionalInfo?: string;\n regDate?: string;\n}\n\ninterface DirectoryMatchRaw {\n participantID: DirectoryParticipantID;\n docTypes?: DirectoryDocType[];\n entities: DirectoryEntity[];\n}\n\ninterface DirectoryResponse {\n \"total-result-count\": number;\n \"result-page-index\": number;\n \"result-page-count\": number;\n matches: DirectoryMatchRaw[];\n}\n\n// ─── Parsing helpers ──────────────────────────────\n\nexport function stripQuotes(name: string): string {\n if (name.startsWith('\"') && name.endsWith('\"') && name.length >= 2) {\n return name.slice(1, -1);\n }\n return name;\n}\n\nexport function pickBestName(\n names: Array<{ name: string; language?: string }>,\n): string {\n if (names.length === 0) return \"\";\n const english = names.find((n) => n.language === \"en\");\n return (english ?? names[0]).name;\n}\n\nexport function mapDocType(urn: string): string | null {\n if (urn.includes(\"Invoice-2::Invoice##\")) return \"invoice\";\n if (urn.includes(\"CreditNote-2::CreditNote##\")) return \"credit_note\";\n if (urn.includes(\"ApplicationResponse\")) return \"application_response\";\n if (urn.includes(\"Order-2::Order##\")) return \"order\";\n if (urn.includes(\"DespatchAdvice\")) return \"despatch_advice\";\n return null;\n}\n\nexport function findVatIdentifier(\n identifiers: Array<{ scheme: string; value: string }>,\n): string | undefined {\n const match = identifiers.find((id) => {\n const s = id.scheme.toLowerCase();\n return s.includes(\"vat\") || s.includes(\"cbe\") || s.includes(\"tax\");\n });\n return match?.value;\n}\n\nexport function parseParticipantId(value: string): {\n scheme: string;\n id: string;\n} {\n const colonIndex = value.indexOf(\":\");\n if (colonIndex === -1) {\n return { scheme: \"\", id: value };\n }\n return {\n scheme: value.slice(0, colonIndex),\n id: value.slice(colonIndex + 1),\n };\n}\n\n// ─── Internal: parse a raw match ──────────────────\n\nfunction parseMatch(raw: DirectoryMatchRaw): DirectoryMatch {\n const entity = raw.entities[0];\n const rawName = entity ? pickBestName(entity.name) : \"\";\n const name = stripQuotes(rawName);\n const country = entity?.countryCode ?? \"\";\n\n const capabilities = (raw.docTypes ?? [])\n .map((dt) => mapDocType(dt.value))\n .filter((c): c is string => c !== null)\n // Deduplicate\n .filter((c, i, arr) => arr.indexOf(c) === i);\n\n const vatNumber = entity?.identifiers\n ? findVatIdentifier(entity.identifiers)\n : undefined;\n\n const contactEmail = entity?.contacts?.find((c) => c.email)?.email;\n const website =\n entity?.websites && entity.websites.length > 0\n ? entity.websites[0]\n : undefined;\n\n return {\n name,\n peppolId: raw.participantID.value,\n country,\n capabilities,\n registrationDate: entity?.regDate,\n vatNumber,\n contactEmail,\n website,\n };\n}\n\n// ─── Public API ───────────────────────────────────\n\nexport async function lookupParticipant(\n scheme: string,\n id: string,\n): Promise<DirectoryMatch | null> {\n const participantParam = `iso6523-actorid-upis::${scheme}:${id}`;\n const url = `${BASE_URL}?participant=${encodeURIComponent(participantParam)}`;\n\n const response = await fetch(url);\n const data = (await response.json()) as DirectoryResponse;\n\n if (!data.matches || data.matches.length === 0) {\n return null;\n }\n\n return parseMatch(data.matches[0]);\n}\n\nexport async function searchParticipants(opts: {\n name?: string;\n country?: string;\n limit?: number;\n}): Promise<SearchResult> {\n const params = new URLSearchParams();\n if (opts.name) params.set(\"name\", opts.name);\n if (opts.country) params.set(\"country\", opts.country);\n\n const url = `${BASE_URL}?${params.toString()}`;\n\n const response = await fetch(url);\n const data = (await response.json()) as DirectoryResponse;\n\n const allMatches = (data.matches ?? []).map(parseMatch);\n\n const limit = opts.limit ?? 10;\n const matches = allMatches.slice(0, limit);\n\n const totalCount = data[\"total-result-count\"] ?? 0;\n const hasMore = totalCount > matches.length;\n\n return {\n matches,\n totalCount,\n hasMore,\n };\n}\n"],"mappings":"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","names":["program","existsSync","resolve","pc","program","resolve","existsSync","pc","writeFileSync","pc","program","writeFileSync","pc","pc","pc","program","require"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/file.ts","../src/formatters/validation.ts","../src/commands/validate.ts","../src/commands/init.ts","../src/templates/invoice.ts","../src/templates/credit-note.ts","../src/commands/convert.ts","../src/commands/lookup.ts","../src/lib/peppol-directory.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport { registerValidateCommand } from \"./commands/validate.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerConvertCommand } from \"./commands/convert.js\";\nimport { registerLookupCommand } from \"./commands/lookup.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"getpeppr\")\n .description(\"CLI tool for Peppol e-invoice validation and development\")\n .version(version);\n\nregisterValidateCommand(program);\nregisterInitCommand(program);\nregisterConvertCommand(program);\nregisterLookupCommand(program);\n\nprogram.parse();\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport type FileReadResult =\n | { ok: true; data: unknown }\n | { ok: false; error: string };\n\nexport function readJsonFile(filePath: string): FileReadResult {\n const resolved = resolve(filePath);\n\n if (!existsSync(resolved)) {\n return { ok: false, error: `Error: file not found — ${resolved}` };\n }\n\n let content: string;\n try {\n content = readFileSync(resolved, \"utf-8\");\n } catch {\n return { ok: false, error: `Error: could not read file — ${resolved}` };\n }\n\n try {\n const data: unknown = JSON.parse(content);\n return { ok: true, data };\n } catch {\n return { ok: false, error: `Error: invalid JSON in file — ${resolved}` };\n }\n}\n","import pc from \"picocolors\";\nimport type { MergedValidationResult } from \"../commands/validate.js\";\nimport type { ValidationError, ValidationWarning, SchematronViolation } from \"@getpeppr/sdk\";\n\nfunction sectionHeader(title: string): string {\n const pad = 45 - title.length - 4;\n return pc.dim(`── ${title} ${\"─\".repeat(Math.max(pad, 3))}`);\n}\n\nfunction formatError(item: ValidationError | SchematronViolation): string {\n const ruleId = \"ruleId\" in item && item.ruleId ? pc.dim(` (${item.ruleId})`) : \"\";\n const field = \"field\" in item && item.field ? `${item.field} — ` : \"\";\n return ` ${pc.red(\"✗\")} ${field}${item.message}${ruleId}`;\n}\n\nfunction formatWarning(item: ValidationWarning | SchematronViolation): string {\n const ruleId = \"ruleId\" in item && item.ruleId ? pc.dim(` (${item.ruleId})`) : \"\";\n const field = \"field\" in item && item.field ? `${item.field} — ` : \"\";\n return ` ${pc.yellow(\"⚠\")} ${field}${item.message}${ruleId}`;\n}\n\nfunction formatSection(\n title: string,\n errors: (ValidationError | SchematronViolation)[],\n warnings: (ValidationWarning | SchematronViolation)[],\n): string {\n const lines: string[] = [sectionHeader(title)];\n\n if (errors.length === 0 && warnings.length === 0) {\n lines.push(` ${pc.green(\"✓\")} All rules passed`);\n return lines.join(\"\\n\");\n }\n\n if (errors.length === 0) {\n lines.push(` ${pc.green(\"✓\")} No errors`);\n }\n\n for (const err of errors) {\n lines.push(formatError(err));\n }\n\n for (const warn of warnings) {\n lines.push(formatWarning(warn));\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function formatValidationResult(\n filename: string,\n result: MergedValidationResult,\n): string {\n const lines: string[] = [];\n\n lines.push(`\\nValidating: ${pc.bold(filename)}\\n`);\n\n lines.push(\n formatSection(\n \"Structure\",\n result.structure.errors,\n result.structure.warnings,\n ),\n );\n lines.push(\"\");\n\n lines.push(\n formatSection(\n \"Business Rules (Peppol BIS 3.0)\",\n result.schematron.errors,\n result.schematron.warnings,\n ),\n );\n lines.push(\"\");\n\n lines.push(\n formatSection(\n \"Country Rules\",\n result.countryRules.errors,\n result.countryRules.warnings,\n ),\n );\n lines.push(\"\");\n\n // Summary\n lines.push(sectionHeader(\"Summary\"));\n const { totalErrors, totalWarnings, valid } = result;\n\n if (valid && totalWarnings === 0) {\n lines.push(` ${pc.green(pc.bold(\"✓ Invoice is valid\"))}`);\n } else if (valid) {\n lines.push(\n ` ${pc.green(pc.bold(\"✓ Invoice is valid\"))} ${pc.dim(`(${totalWarnings} warning${totalWarnings === 1 ? \"\" : \"s\"})`)}`,\n );\n } else {\n const parts: string[] = [];\n parts.push(`${totalErrors} error${totalErrors === 1 ? \"\" : \"s\"}`);\n if (totalWarnings > 0) {\n parts.push(`${totalWarnings} warning${totalWarnings === 1 ? \"\" : \"s\"}`);\n }\n lines.push(\n ` ${pc.red(pc.bold(`✗ ${parts.join(\", \")}`))} — invoice non-compliant`,\n );\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n","import type { Command } from \"commander\";\nimport { readJsonFile } from \"../utils/file.js\";\nimport { formatValidationResult } from \"../formatters/validation.js\";\nimport {\n validateInvoice,\n validateSchematron,\n validateCountryRules,\n type InvoiceInput,\n type ValidationError,\n type ValidationWarning,\n type SchematronViolation,\n} from \"@getpeppr/sdk\";\n\nexport interface MergedValidationResult {\n structure: {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n };\n schematron: {\n errors: SchematronViolation[];\n warnings: SchematronViolation[];\n };\n countryRules: {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n };\n totalErrors: number;\n totalWarnings: number;\n valid: boolean;\n}\n\nexport function runValidation(input: InvoiceInput): MergedValidationResult {\n const structure = validateInvoice(input);\n const schematron = validateSchematron(input);\n const countryRules = validateCountryRules(input);\n\n const totalErrors =\n structure.errors.length +\n schematron.errors.length +\n countryRules.errors.length;\n\n const totalWarnings =\n structure.warnings.length +\n schematron.warnings.length +\n countryRules.warnings.length;\n\n return {\n structure: { errors: structure.errors, warnings: structure.warnings },\n schematron: { errors: schematron.errors, warnings: schematron.warnings },\n countryRules: {\n errors: countryRules.errors,\n warnings: countryRules.warnings,\n },\n totalErrors,\n totalWarnings,\n valid: totalErrors === 0,\n };\n}\n\nexport function registerValidateCommand(program: Command): void {\n program\n .command(\"validate\")\n .description(\"Validate a Peppol invoice JSON file\")\n .argument(\"<file>\", \"path to invoice JSON file\")\n .option(\"--json\", \"output results as JSON\")\n .option(\"--quiet\", \"exit code only, no output\")\n .action(async (file: string, options: { json?: boolean; quiet?: boolean }) => {\n // 1. Read and parse the JSON file\n // Fatal errors always go to stderr regardless of --quiet (UNIX convention)\n const parseResult = readJsonFile(file);\n if (!parseResult.ok) {\n process.stderr.write(parseResult.error + \"\\n\");\n process.exit(2);\n }\n\n if (\n typeof parseResult.data !== \"object\" ||\n parseResult.data === null ||\n Array.isArray(parseResult.data)\n ) {\n process.stderr.write(\n \"Error: JSON file must contain an object, not an array or primitive\\n\",\n );\n process.exit(2);\n }\n\n const input = parseResult.data as InvoiceInput;\n\n // 2. Run all 3 validators\n const result = runValidation(input);\n\n // 3. Output\n if (options.quiet) {\n process.exit(result.valid ? 0 : 1);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n process.exit(result.valid ? 0 : 1);\n }\n\n // 4. Formatted output\n const output = formatValidationResult(file, result);\n console.log(output);\n process.exit(result.valid ? 0 : 1);\n });\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { INVOICE_TEMPLATE } from \"../templates/invoice.js\";\nimport { CREDIT_NOTE_TEMPLATE } from \"../templates/credit-note.js\";\n\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .description(\"Scaffold a starter invoice JSON file\")\n .argument(\"[filename]\", \"output filename\", \"invoice.json\")\n .option(\"--credit-note\", \"generate a credit note template instead\")\n .option(\"--force\", \"overwrite existing file\")\n .action(\n (\n filename: string,\n options: { creditNote?: boolean; force?: boolean },\n ) => {\n const resolved = resolve(filename);\n\n if (existsSync(resolved) && !options.force) {\n console.error(\n `Error: ${filename} already exists. Use --force to overwrite.`,\n );\n process.exit(2);\n }\n\n const template = options.creditNote\n ? CREDIT_NOTE_TEMPLATE\n : INVOICE_TEMPLATE;\n\n try {\n writeFileSync(\n resolved,\n JSON.stringify(template, null, 2) + \"\\n\",\n \"utf-8\",\n );\n } catch {\n console.error(`Error: could not write file — ${resolved}`);\n process.exit(2);\n }\n\n console.error(`${pc.green(\"\\u2713\")} Created ${filename}\n\n Next steps:\n 1. Edit the file with your invoice data\n 2. Validate: getpeppr validate ${filename}\n 3. Convert to XML: getpeppr convert ${filename}`);\n\n process.exit(0);\n },\n );\n}\n","import type { InvoiceInput } from \"@getpeppr/sdk\";\n\nexport const INVOICE_TEMPLATE: InvoiceInput = {\n number: \"INV-2026-001\",\n date: \"2026-01-15\",\n dueDate: \"2026-02-15\",\n currency: \"EUR\",\n buyerReference: \"PO-2026-042\",\n from: {\n name: \"Dupont & Fils SPRL\",\n peppolId: \"0208:BE0123456789\",\n street: \"Avenue Louise 54\",\n city: \"Bruxelles\",\n postalCode: \"1050\",\n country: \"BE\",\n },\n to: {\n name: \"M\\u00fcller & Partner GmbH\",\n peppolId: \"0204:DE987654321\",\n street: \"Friedrichstra\\u00dfe 123\",\n city: \"Berlin\",\n postalCode: \"10117\",\n country: \"DE\",\n },\n lines: [\n {\n description: \"Conseil en transformation num\\u00e9rique\",\n quantity: 10,\n unitPrice: 950,\n vatRate: 21,\n },\n {\n description: \"Software license \\u2014 annual subscription\",\n quantity: 1,\n unitPrice: 2400,\n vatRate: 0,\n vatCategory: \"AE\",\n },\n ],\n paymentTerms: \"Net 30 days\",\n paymentReference: \"+++000/0000/00097+++\",\n};\n","import type { InvoiceInput } from \"@getpeppr/sdk\";\n\nexport const CREDIT_NOTE_TEMPLATE: InvoiceInput = {\n number: \"CN-2026-001\",\n date: \"2026-02-01\",\n currency: \"EUR\",\n isCreditNote: true,\n invoiceReference: \"INV-2026-001\",\n from: {\n name: \"Dupont & Fils SPRL\",\n peppolId: \"0208:BE0123456789\",\n street: \"Avenue Louise 54\",\n city: \"Bruxelles\",\n postalCode: \"1050\",\n country: \"BE\",\n },\n to: {\n name: \"M\\u00fcller & Partner GmbH\",\n peppolId: \"0204:DE987654321\",\n street: \"Friedrichstra\\u00dfe 123\",\n city: \"Berlin\",\n postalCode: \"10117\",\n country: \"DE\",\n },\n lines: [\n {\n description: \"Avoir partiel \\u2014 Conseil en transformation num\\u00e9rique\",\n quantity: 2,\n unitPrice: 950,\n vatRate: 21,\n },\n ],\n note: \"Avoir pour prestations non r\\u00e9alis\\u00e9es \\u2014 r\\u00e9f. INV-2026-001\",\n};\n","import { writeFileSync } from \"node:fs\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { readJsonFile } from \"../utils/file.js\";\nimport { runValidation } from \"./validate.js\";\nimport { formatValidationResult } from \"../formatters/validation.js\";\nimport {\n buildInvoiceXml,\n buildCreditNoteXml,\n type InvoiceInput,\n type CreditNoteInput,\n} from \"@getpeppr/sdk\";\n\nexport function registerConvertCommand(program: Command): void {\n program\n .command(\"convert\")\n .description(\n \"Convert a getpeppr JSON invoice to Peppol BIS 3.0 UBL XML\",\n )\n .argument(\"<file>\", \"path to invoice JSON file\")\n .option(\"-o, --output <file>\", \"write XML to file instead of stdout\")\n .option(\"--validate\", \"validate the invoice before converting\")\n .action(\n async (\n file: string,\n options: { output?: string; validate?: boolean },\n ) => {\n // 1. Read and parse the JSON file\n const parseResult = readJsonFile(file);\n if (!parseResult.ok) {\n process.stderr.write(parseResult.error + \"\\n\");\n process.exit(2);\n }\n\n if (\n typeof parseResult.data !== \"object\" ||\n parseResult.data === null ||\n Array.isArray(parseResult.data)\n ) {\n process.stderr.write(\n \"Error: JSON file must contain an object, not an array or primitive\\n\",\n );\n process.exit(2);\n }\n\n const input = parseResult.data as InvoiceInput;\n\n // 2. If --validate, run validation first\n if (options.validate) {\n const result = runValidation(input);\n const formatted = formatValidationResult(file, result);\n\n if (!result.valid) {\n // Errors: show on stderr, exit 1, NO XML\n process.stderr.write(formatted + \"\\n\");\n process.exit(1);\n }\n\n if (result.totalWarnings > 0) {\n // Warnings only: show on stderr, continue to conversion\n process.stderr.write(formatted + \"\\n\");\n }\n }\n\n // 3. Detect document type\n const isCreditNote = input.isCreditNote === true;\n\n // 4. Generate XML\n let xml: string;\n try {\n if (isCreditNote) {\n xml = buildCreditNoteXml(input as CreditNoteInput);\n } else {\n xml = buildInvoiceXml(input);\n }\n } catch (err: unknown) {\n const message =\n err instanceof Error ? err.message : \"Unknown error\";\n process.stderr.write(`Error: XML generation failed — ${message}\\n`);\n process.exit(2);\n }\n\n // 5. Clean empty lines from XML\n xml = xml.replace(/^[ \\t]*\\n/gm, \"\");\n\n // 6. Output\n const docType = isCreditNote\n ? \"UBL 2.1 CreditNote\"\n : \"UBL 2.1 Invoice\";\n\n if (options.output) {\n writeFileSync(options.output, xml, \"utf-8\");\n process.stderr.write(\n `${pc.green(\"✓\")} Converted to ${options.output} (${docType})\\n`,\n );\n } else {\n process.stdout.write(xml + \"\\n\");\n }\n },\n );\n}\n","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport {\n lookupParticipant,\n searchParticipants,\n type DirectoryMatch,\n type SearchResult,\n} from \"../lib/peppol-directory.js\";\n\n// ─── Country name helper ──────────────────────────\n\nconst COUNTRY_NAMES: Record<string, string> = {\n AT: \"Austria\",\n BE: \"Belgium\",\n BG: \"Bulgaria\",\n HR: \"Croatia\",\n CY: \"Cyprus\",\n CZ: \"Czechia\",\n DK: \"Denmark\",\n EE: \"Estonia\",\n FI: \"Finland\",\n FR: \"France\",\n DE: \"Germany\",\n GR: \"Greece\",\n HU: \"Hungary\",\n IS: \"Iceland\",\n IE: \"Ireland\",\n IT: \"Italy\",\n LV: \"Latvia\",\n LT: \"Lithuania\",\n LU: \"Luxembourg\",\n MT: \"Malta\",\n NL: \"Netherlands\",\n NO: \"Norway\",\n PL: \"Poland\",\n PT: \"Portugal\",\n RO: \"Romania\",\n SK: \"Slovakia\",\n SI: \"Slovenia\",\n ES: \"Spain\",\n SE: \"Sweden\",\n CH: \"Switzerland\",\n GB: \"United Kingdom\",\n US: \"United States\",\n AU: \"Australia\",\n CA: \"Canada\",\n SG: \"Singapore\",\n JP: \"Japan\",\n NZ: \"New Zealand\",\n};\n\nfunction countryLabel(code: string): string {\n const name = COUNTRY_NAMES[code.toUpperCase()];\n return name ? `${name} (${code})` : code;\n}\n\n// ─── Output formatting ───────────────────────────\n\nfunction formatLookupResult(match: DirectoryMatch): string {\n const lines: string[] = [];\n lines.push(`${pc.green(\"\\u2713\")} ${match.name}`);\n lines.push(` ${pc.dim(\"Peppol ID\")} ${match.peppolId}`);\n lines.push(` ${pc.dim(\"Country\")} ${countryLabel(match.country)}`);\n if (match.registrationDate) {\n lines.push(` ${pc.dim(\"Registered\")} ${match.registrationDate}`);\n }\n if (match.vatNumber) {\n lines.push(` ${pc.dim(\"VAT\")} ${match.vatNumber}`);\n }\n if (match.capabilities.length > 0) {\n lines.push(\n ` ${pc.dim(\"Capabilities\")} ${match.capabilities.join(\", \")}`,\n );\n }\n if (match.contactEmail) {\n lines.push(` ${pc.dim(\"Contact\")} ${match.contactEmail}`);\n }\n if (match.website) {\n lines.push(` ${pc.dim(\"Website\")} ${match.website}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatSearchResults(result: SearchResult): string {\n const lines: string[] = [];\n const plural = result.totalCount === 1 ? \"participant\" : \"participants\";\n lines.push(`Found ${result.totalCount} ${plural}:\\n`);\n\n // Column headers\n const nameW = 26;\n const idW = 23;\n const countryW = 9;\n\n lines.push(\n ` ${\"Name\".padEnd(nameW)}${\"Peppol ID\".padEnd(idW)}${\"Country\".padEnd(countryW)}Capabilities`,\n );\n lines.push(` ${\"─\".repeat(nameW + idW + countryW + 20)}`);\n\n for (const m of result.matches) {\n const name = m.name.length > nameW - 1 ? m.name.slice(0, nameW - 2) + \"…\" : m.name;\n const caps = m.capabilities.join(\", \");\n lines.push(\n ` ${name.padEnd(nameW)}${m.peppolId.padEnd(idW)}${m.country.padEnd(countryW)}${caps}`,\n );\n }\n\n if (result.hasMore) {\n lines.push(\n `\\n ${pc.dim(`Showing ${result.matches.length} of ${result.totalCount} results.`)}`,\n );\n }\n\n return lines.join(\"\\n\");\n}\n\n// ─── Input validation ─────────────────────────────\n\nfunction validatePeppolId(raw: string): {\n ok: true;\n scheme: string;\n id: string;\n} | { ok: false; error: string } {\n const colonIndex = raw.indexOf(\":\");\n if (colonIndex === -1) {\n return {\n ok: false,\n error: `Invalid Peppol ID format: \"${raw}\". Expected format: scheme:id (e.g. 0208:BE0685660237)`,\n };\n }\n\n const scheme = raw.slice(0, colonIndex);\n const id = raw.slice(colonIndex + 1);\n\n if (!/^\\d{4}$/.test(scheme)) {\n return {\n ok: false,\n error: `Invalid scheme \"${scheme}\". Must be exactly 4 digits (e.g. 0208).`,\n };\n }\n\n if (!/^[A-Za-z0-9:.\\-]+$/.test(id)) {\n return {\n ok: false,\n error: `Invalid participant ID \"${id}\". Only letters, digits, colons, dots and hyphens are allowed.`,\n };\n }\n\n return { ok: true, scheme, id };\n}\n\n// ─── Command registration ─────────────────────────\n\nexport function registerLookupCommand(program: Command): void {\n program\n .command(\"lookup\")\n .description(\"Look up a participant in the Peppol Directory\")\n .argument(\"[peppolId]\", \"Peppol participant ID (format: scheme:id)\")\n .option(\"--name <name>\", \"search by company name (min 3 chars)\")\n .option(\"--country <code>\", \"filter by ISO 2-letter country code\")\n .option(\"--json\", \"output results as JSON\")\n .option(\"--limit <n>\", \"max results (default 10)\", \"10\")\n .action(\n async (\n peppolId: string | undefined,\n options: {\n name?: string;\n country?: string;\n json?: boolean;\n limit?: string;\n },\n ) => {\n const isSearch = Boolean(options.name);\n const isLookup = Boolean(peppolId);\n\n // Must have at least one criterion\n if (!isSearch && !isLookup) {\n process.stderr.write(\n \"Provide a Peppol ID or use --name to search.\\n\",\n );\n process.exit(2);\n }\n\n // Validate --country format\n if (options.country) {\n const normalized = options.country.toUpperCase();\n if (!/^[A-Z]{2}$/.test(normalized)) {\n process.stderr.write(\n `Invalid country code \"${options.country}\". Must be 2 letters (e.g. BE, DE, FR).\\n`,\n );\n process.exit(2);\n }\n options.country = normalized;\n }\n\n if (isLookup) {\n await handleLookup(peppolId!, options);\n } else {\n await handleSearch(options);\n }\n },\n );\n}\n\n// ─── Lookup handler ───────────────────────────────\n\nasync function handleLookup(\n peppolId: string,\n options: { json?: boolean },\n): Promise<void> {\n const parsed = validatePeppolId(peppolId);\n if (!parsed.ok) {\n process.stderr.write(parsed.error + \"\\n\");\n process.exit(2);\n }\n\n let result: DirectoryMatch | null;\n\n try {\n result = await lookupParticipant(parsed.scheme, parsed.id);\n } catch {\n process.stderr.write(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.\\n`,\n );\n process.exit(2);\n }\n\n if (!result) {\n if (options.json) {\n console.log(JSON.stringify(null));\n } else {\n process.stderr.write(\n `${pc.red(\"\\u2717\")} Participant not found: ${peppolId}\\n`,\n );\n }\n process.exit(1);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatLookupResult(result));\n }\n process.exit(0);\n}\n\n// ─── Search handler ───────────────────────────────\n\nasync function handleSearch(options: {\n name?: string;\n country?: string;\n json?: boolean;\n limit?: string;\n}): Promise<void> {\n if (options.name && options.name.length < 3) {\n process.stderr.write(\n `Search name must be at least 3 characters. Got: \"${options.name}\"\\n`,\n );\n process.exit(2);\n }\n\n const limit = parseInt(options.limit ?? \"10\", 10);\n\n let result: SearchResult;\n\n try {\n result = await searchParticipants({\n name: options.name,\n country: options.country,\n limit,\n });\n } catch {\n process.stderr.write(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.\\n`,\n );\n process.exit(2);\n }\n\n if (result.matches.length === 0) {\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n process.stderr.write(\"No participants found.\\n\");\n }\n process.exit(1);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatSearchResults(result));\n }\n process.exit(0);\n}\n","const BASE_URL = \"https://directory.peppol.eu/search/1.0/json\";\n\n// ─── Public types ─────────────────────────────────\n\nexport interface DirectoryMatch {\n name: string;\n peppolId: string;\n country: string;\n capabilities: string[];\n registrationDate?: string;\n vatNumber?: string;\n contactEmail?: string;\n website?: string;\n}\n\nexport interface SearchResult {\n matches: DirectoryMatch[];\n totalCount: number;\n hasMore: boolean;\n}\n\n// ─── Response types (Peppol Directory JSON) ───────\n\ninterface DirectoryParticipantID {\n scheme: string;\n value: string;\n}\n\ninterface DirectoryDocType {\n scheme: string;\n value: string;\n}\n\ninterface DirectoryEntity {\n name: Array<{ name: string; language?: string }>;\n countryCode: string;\n geoInfo?: string;\n identifiers?: Array<{ scheme: string; value: string }>;\n websites?: string[];\n contacts?: Array<{ type: string; name?: string; email?: string }>;\n additionalInfo?: string;\n regDate?: string;\n}\n\ninterface DirectoryMatchRaw {\n participantID: DirectoryParticipantID;\n docTypes?: DirectoryDocType[];\n entities: DirectoryEntity[];\n}\n\ninterface DirectoryResponse {\n \"total-result-count\": number;\n \"result-page-index\": number;\n \"result-page-count\": number;\n matches: DirectoryMatchRaw[];\n}\n\n// ─── Parsing helpers ──────────────────────────────\n\nexport function stripQuotes(name: string): string {\n if (name.startsWith('\"') && name.endsWith('\"') && name.length >= 2) {\n return name.slice(1, -1);\n }\n return name;\n}\n\nexport function pickBestName(\n names: Array<{ name: string; language?: string }>,\n): string {\n if (names.length === 0) return \"\";\n const english = names.find((n) => n.language === \"en\");\n return (english ?? names[0]).name;\n}\n\nexport function mapDocType(urn: string): string | null {\n if (urn.includes(\"Invoice-2::Invoice##\")) return \"invoice\";\n if (urn.includes(\"CreditNote-2::CreditNote##\")) return \"credit_note\";\n if (urn.includes(\"ApplicationResponse\")) return \"application_response\";\n if (urn.includes(\"Order-2::Order##\")) return \"order\";\n if (urn.includes(\"DespatchAdvice\")) return \"despatch_advice\";\n return null;\n}\n\nexport function findVatIdentifier(\n identifiers: Array<{ scheme: string; value: string }>,\n): string | undefined {\n const match = identifiers.find((id) => {\n const s = id.scheme.toLowerCase();\n return s.includes(\"vat\") || s.includes(\"cbe\") || s.includes(\"tax\");\n });\n return match?.value;\n}\n\nexport function parseParticipantId(value: string): {\n scheme: string;\n id: string;\n} {\n const colonIndex = value.indexOf(\":\");\n if (colonIndex === -1) {\n return { scheme: \"\", id: value };\n }\n return {\n scheme: value.slice(0, colonIndex),\n id: value.slice(colonIndex + 1),\n };\n}\n\n// ─── Internal: parse a raw match ──────────────────\n\nfunction parseMatch(raw: DirectoryMatchRaw): DirectoryMatch {\n const entity = raw.entities[0];\n const rawName = entity ? pickBestName(entity.name) : \"\";\n const name = stripQuotes(rawName);\n const country = entity?.countryCode ?? \"\";\n\n const capabilities = (raw.docTypes ?? [])\n .map((dt) => mapDocType(dt.value))\n .filter((c): c is string => c !== null)\n // Deduplicate\n .filter((c, i, arr) => arr.indexOf(c) === i);\n\n const vatNumber = entity?.identifiers\n ? findVatIdentifier(entity.identifiers)\n : undefined;\n\n const contactEmail = entity?.contacts?.find((c) => c.email)?.email;\n const website =\n entity?.websites && entity.websites.length > 0\n ? entity.websites[0]\n : undefined;\n\n return {\n name,\n peppolId: raw.participantID.value,\n country,\n capabilities,\n registrationDate: entity?.regDate,\n vatNumber,\n contactEmail,\n website,\n };\n}\n\n// ─── Public API ───────────────────────────────────\n\nexport async function lookupParticipant(\n scheme: string,\n id: string,\n): Promise<DirectoryMatch | null> {\n const participantParam = `iso6523-actorid-upis::${scheme}:${id}`;\n const url = `${BASE_URL}?participant=${encodeURIComponent(participantParam)}`;\n\n const response = await fetch(url);\n const data = (await response.json()) as DirectoryResponse;\n\n if (!data.matches || data.matches.length === 0) {\n return null;\n }\n\n return parseMatch(data.matches[0]);\n}\n\nexport async function searchParticipants(opts: {\n name?: string;\n country?: string;\n limit?: number;\n}): Promise<SearchResult> {\n const params = new URLSearchParams();\n if (opts.name) params.set(\"name\", opts.name);\n if (opts.country) params.set(\"country\", opts.country);\n\n const url = `${BASE_URL}?${params.toString()}`;\n\n const response = await fetch(url);\n const data = (await response.json()) as DirectoryResponse;\n\n const allMatches = (data.matches ?? []).map(parseMatch);\n\n const limit = opts.limit ?? 10;\n const matches = allMatches.slice(0, limit);\n\n const totalCount = data[\"total-result-count\"] ?? 0;\n const hasMore = totalCount > matches.length;\n\n return {\n matches,\n totalCount,\n hasMore,\n };\n}\n"],"mappings":"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","names":["program","existsSync","resolve","pc","program","resolve","existsSync","pc","writeFileSync","pc","program","writeFileSync","pc","pc","pc","program","require"]}
|