@getpeppr/cli 0.4.5 → 0.4.7

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/file.ts","../src/utils/errors.ts","../src/formatters/validation.ts","../../sdk/src/core/ubl-builder.ts","../../sdk/src/core/country-rules.ts","../../sdk/src/core/code-lists.ts","../../sdk/src/core/validator.ts","../../sdk/src/version.ts","../../sdk/src/core/client.ts","../../sdk/src/core/schematron.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","../src/commands/send.ts","../src/lib/credentials-store.ts","../src/lib/auth.ts","../src/lib/send-payload.ts","../src/templates/send-default.ts","../src/lib/confirm.ts","../src/lib/watch.ts","../src/formatters/send-result.ts","../src/commands/login.ts","../src/commands/logout.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\";\nimport { registerSendCommand } from \"./commands/send.js\";\nimport { registerLoginCommand } from \"./commands/login.js\";\nimport { registerLogoutCommand } from \"./commands/logout.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);\nregisterSendCommand(program);\nregisterLoginCommand(program);\nregisterLogoutCommand(program);\n\nprogram.parse();\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { InvoiceInput } from \"@getpeppr/sdk\";\nimport { exitWithError } from \"./errors.js\";\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\nexport function readAndValidateInvoiceJson(filePath: string): InvoiceInput {\n const parseResult = readJsonFile(filePath);\n if (!parseResult.ok) {\n exitWithError(parseResult.error);\n }\n\n if (\n typeof parseResult.data !== \"object\" ||\n parseResult.data === null ||\n Array.isArray(parseResult.data)\n ) {\n exitWithError(\n \"Error: JSON file must contain an object, not an array or primitive\",\n );\n }\n\n return parseResult.data as InvoiceInput;\n}\n","export function exitWithError(message: string, code = 2): never {\n process.stderr.write(message + \"\\n\");\n process.exit(code);\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","/**\n * UBL XML Builder\n *\n * Converts our clean JSON invoice format to Peppol BIS 3.0 compliant UBL 2.1 XML.\n * This is the core abstraction that hides XML complexity from developers.\n *\n * Reference: https://docs.peppol.eu/poacc/billing/3.0/\n */\n\nimport type { InvoiceInput, CreditNoteInput, InvoiceLine, Party, Delivery, AllowanceCharge, Attachment, InvoicePeriod } from \"../types/invoice.js\";\n\nconst UBL_NS = \"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\";\nconst CAC_NS = \"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2\";\nconst CBC_NS = \"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2\";\nconst CREDIT_NOTE_NS = \"urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2\";\n\n// Peppol BIS 3.0 customization and profile IDs\nconst PEPPOL_CUSTOMIZATION_ID =\n \"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\";\nconst PEPPOL_PROFILE_ID = \"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0\";\n\n/** Default unit of measure */\nconst DEFAULT_UNIT = \"EA\";\n\n/** Default payment means code (30 = credit transfer) */\nconst DEFAULT_PAYMENT_MEANS = 30;\n\n/** Map human-readable unit names to UN/ECE Recommendation 20 codes */\nconst UNIT_CODE_MAP: Record<string, string> = {\n each: \"EA\", piece: \"EA\", pieces: \"EA\",\n hour: \"HUR\", hours: \"HUR\",\n day: \"DAY\", days: \"DAY\",\n week: \"WEE\", weeks: \"WEE\",\n month: \"MON\", months: \"MON\",\n year: \"ANN\", years: \"ANN\",\n kilogram: \"KGM\", kg: \"KGM\",\n meter: \"MTR\", metre: \"MTR\",\n liter: \"LTR\", litre: \"LTR\",\n unit: \"C62\", units: \"C62\",\n set: \"SET\", sets: \"SET\",\n pack: \"PK\", packs: \"PK\",\n};\n\n/**\n * Resolve a human-readable unit name to its UN/ECE Recommendation 20 code.\n * If already a valid UBL code (2-3 uppercase chars) or unknown, passes through unchanged.\n */\nfunction resolveUnitCode(unit: string): string {\n return UNIT_CODE_MAP[unit.toLowerCase()] ?? unit;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction formatDate(dateStr?: string): string {\n if (!dateStr) {\n return new Date().toISOString().split(\"T\")[0]!;\n }\n // Accept ISO 8601 date or datetime\n return dateStr.split(\"T\")[0]!;\n}\n\nfunction formatAmount(amount: number): string {\n return amount.toFixed(2);\n}\n\n/** Round to 2 decimal places to prevent IEEE 754 accumulation errors */\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction parsePeppolId(peppolId: string): { scheme: string; id: string } {\n const scheme = peppolId.split(\":\")[0]!;\n const id = peppolId.split(\":\").slice(1).join(\":\");\n return { scheme, id };\n}\n\nfunction buildPartyXml(party: Party, role: \"AccountingSupplierParty\" | \"AccountingCustomerParty\"): string {\n const { scheme: endpointScheme, id: endpointId } = parsePeppolId(party.peppolId);\n\n return `\n <cac:${role}>\n <cac:Party>\n <cbc:EndpointID schemeID=\"${escapeXml(endpointScheme)}\">${escapeXml(endpointId)}</cbc:EndpointID>\n <cac:PartyIdentification>\n <cbc:ID schemeID=\"${escapeXml(endpointScheme)}\">${escapeXml(endpointId)}</cbc:ID>\n </cac:PartyIdentification>\n <cac:PartyName>\n <cbc:Name>${escapeXml(party.name)}</cbc:Name>\n </cac:PartyName>\n <cac:PostalAddress>\n ${party.street ? `<cbc:StreetName>${escapeXml(party.street)}</cbc:StreetName>` : \"\"}\n ${party.city ? `<cbc:CityName>${escapeXml(party.city)}</cbc:CityName>` : \"\"}\n ${party.postalCode ? `<cbc:PostalZone>${escapeXml(party.postalCode)}</cbc:PostalZone>` : \"\"}\n <cac:Country>\n <cbc:IdentificationCode>${escapeXml(party.country)}</cbc:IdentificationCode>\n </cac:Country>\n </cac:PostalAddress>\n ${\n party.vatNumber\n ? `<cac:PartyTaxScheme>\n <cbc:CompanyID>${escapeXml(party.vatNumber)}</cbc:CompanyID>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:PartyTaxScheme>`\n : \"\"\n }\n <cac:PartyLegalEntity>\n <cbc:RegistrationName>${escapeXml(party.name)}</cbc:RegistrationName>\n ${party.companyId ? `<cbc:CompanyID>${escapeXml(party.companyId)}</cbc:CompanyID>` : \"\"}\n </cac:PartyLegalEntity>\n ${(party.contactName || party.phone || party.email)\n ? `<cac:Contact>\n ${party.contactName ? `<cbc:Name>${escapeXml(party.contactName)}</cbc:Name>` : \"\"}\n ${party.phone ? `<cbc:Telephone>${escapeXml(party.phone)}</cbc:Telephone>` : \"\"}\n ${party.email ? `<cbc:ElectronicMail>${escapeXml(party.email)}</cbc:ElectronicMail>` : \"\"}\n </cac:Contact>`\n : \"\"\n }\n </cac:Party>\n </cac:${role}>`;\n}\n\nfunction buildPayeePartyXml(party: Party): string {\n const { scheme, id } = parsePeppolId(party.peppolId);\n\n return `\n <cac:PayeeParty>\n <cac:PartyIdentification>\n <cbc:ID schemeID=\"${escapeXml(scheme)}\">${escapeXml(id)}</cbc:ID>\n </cac:PartyIdentification>\n <cac:PartyName>\n <cbc:Name>${escapeXml(party.name)}</cbc:Name>\n </cac:PartyName>\n ${party.companyId\n ? `<cac:PartyLegalEntity>\n <cbc:RegistrationName>${escapeXml(party.name)}</cbc:RegistrationName>\n <cbc:CompanyID>${escapeXml(party.companyId)}</cbc:CompanyID>\n </cac:PartyLegalEntity>`\n : \"\"\n }\n </cac:PayeeParty>`;\n}\n\nfunction buildTaxRepresentativePartyXml(party: Party): string {\n const parts: string[] = [\n \" <cac:TaxRepresentativeParty>\",\n \" <cac:PartyName>\",\n ` <cbc:Name>${escapeXml(party.name)}</cbc:Name>`,\n \" </cac:PartyName>\",\n ];\n\n // PostalAddress\n parts.push(\" <cac:PostalAddress>\");\n if (party.street) {\n parts.push(` <cbc:StreetName>${escapeXml(party.street)}</cbc:StreetName>`);\n }\n if (party.city) {\n parts.push(` <cbc:CityName>${escapeXml(party.city)}</cbc:CityName>`);\n }\n if (party.postalCode) {\n parts.push(` <cbc:PostalZone>${escapeXml(party.postalCode)}</cbc:PostalZone>`);\n }\n parts.push(\" <cac:Country>\");\n parts.push(` <cbc:IdentificationCode>${escapeXml(party.country)}</cbc:IdentificationCode>`);\n parts.push(\" </cac:Country>\");\n parts.push(\" </cac:PostalAddress>\");\n\n // PartyTaxScheme (vatNumber → CompanyID)\n if (party.vatNumber) {\n parts.push(\" <cac:PartyTaxScheme>\");\n parts.push(` <cbc:CompanyID>${escapeXml(party.vatNumber)}</cbc:CompanyID>`);\n parts.push(\" <cac:TaxScheme>\");\n parts.push(\" <cbc:ID>VAT</cbc:ID>\");\n parts.push(\" </cac:TaxScheme>\");\n parts.push(\" </cac:PartyTaxScheme>\");\n }\n\n parts.push(\" </cac:TaxRepresentativeParty>\");\n return parts.join(\"\\n\");\n}\n\nfunction buildAttachmentXml(attachment: Attachment): string {\n const parts: string[] = [\n \"<cac:AdditionalDocumentReference>\",\n ` <cbc:ID>${escapeXml(attachment.id)}</cbc:ID>`,\n ];\n\n if (attachment.description) {\n parts.push(` <cbc:DocumentDescription>${escapeXml(attachment.description)}</cbc:DocumentDescription>`);\n }\n\n if (attachment.content || attachment.url) {\n parts.push(\" <cac:Attachment>\");\n if (attachment.content && attachment.mimeType && attachment.filename) {\n parts.push(\n ` <cbc:EmbeddedDocumentBinaryObject mimeCode=\"${escapeXml(attachment.mimeType)}\" filename=\"${escapeXml(attachment.filename)}\">${attachment.content}</cbc:EmbeddedDocumentBinaryObject>`,\n );\n } else if (attachment.url) {\n parts.push(\n ` <cac:ExternalReference>\\n <cbc:URI>${escapeXml(attachment.url)}</cbc:URI>\\n </cac:ExternalReference>`,\n );\n }\n parts.push(\" </cac:Attachment>\");\n }\n\n parts.push(\"</cac:AdditionalDocumentReference>\");\n return parts.join(\"\\n \");\n}\n\nfunction buildInvoicePeriodXml(period: InvoicePeriod): string {\n const parts: string[] = [\"<cac:InvoicePeriod>\"];\n if (period.startDate) {\n parts.push(` <cbc:StartDate>${formatDate(period.startDate)}</cbc:StartDate>`);\n }\n if (period.endDate) {\n parts.push(` <cbc:EndDate>${formatDate(period.endDate)}</cbc:EndDate>`);\n }\n parts.push(\"</cac:InvoicePeriod>\");\n return parts.join(\"\\n \");\n}\n\nfunction buildDeliveryXml(delivery: Delivery): string {\n const parts: string[] = [\"<cac:Delivery>\"];\n\n if (delivery.date) {\n parts.push(` <cbc:ActualDeliveryDate>${formatDate(delivery.date)}</cbc:ActualDeliveryDate>`);\n }\n\n if (delivery.locationId || delivery.address) {\n parts.push(\" <cac:DeliveryLocation>\");\n if (delivery.locationId) {\n parts.push(` <cbc:ID>${escapeXml(delivery.locationId)}</cbc:ID>`);\n }\n if (delivery.address) {\n parts.push(\" <cac:Address>\");\n if (delivery.address.street) {\n parts.push(` <cbc:StreetName>${escapeXml(delivery.address.street)}</cbc:StreetName>`);\n }\n if (delivery.address.city) {\n parts.push(` <cbc:CityName>${escapeXml(delivery.address.city)}</cbc:CityName>`);\n }\n if (delivery.address.postalCode) {\n parts.push(` <cbc:PostalZone>${escapeXml(delivery.address.postalCode)}</cbc:PostalZone>`);\n }\n parts.push(` <cac:Country>\\n <cbc:IdentificationCode>${escapeXml(delivery.address.country)}</cbc:IdentificationCode>\\n </cac:Country>`);\n parts.push(\" </cac:Address>\");\n }\n parts.push(\" </cac:DeliveryLocation>\");\n }\n\n parts.push(\"</cac:Delivery>\");\n return parts.join(\"\\n \");\n}\n\nfunction buildDocumentAllowanceChargeXml(\n item: AllowanceCharge,\n isCharge: boolean,\n currency: string,\n): string {\n const vatCategory = item.vatCategory ?? \"S\";\n return `\n <cac:AllowanceCharge>\n <cbc:ChargeIndicator>${isCharge}</cbc:ChargeIndicator>\n <cbc:AllowanceChargeReason>${escapeXml(item.reason)}</cbc:AllowanceChargeReason>\n <cbc:Amount currencyID=\"${escapeXml(currency)}\">${formatAmount(item.amount)}</cbc:Amount>\n <cac:TaxCategory>\n <cbc:ID>${vatCategory}</cbc:ID>\n <cbc:Percent>${item.vatRate}</cbc:Percent>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:TaxCategory>\n </cac:AllowanceCharge>`;\n}\n\nfunction buildLineAllowanceChargeXml(\n reason: string,\n amount: number,\n isCharge: boolean,\n currency: string,\n): string {\n return `\n <cac:AllowanceCharge>\n <cbc:ChargeIndicator>${isCharge}</cbc:ChargeIndicator>\n <cbc:AllowanceChargeReason>${escapeXml(reason)}</cbc:AllowanceChargeReason>\n <cbc:Amount currencyID=\"${escapeXml(currency)}\">${formatAmount(amount)}</cbc:Amount>\n </cac:AllowanceCharge>`;\n}\n\nfunction calculateLineExtensionAmount(line: InvoiceLine): number {\n const base = line.quantity * line.unitPrice;\n const lineAllowances = (line.allowances ?? []).reduce((sum, a) => sum + a.amount, 0);\n const lineCharges = (line.charges ?? []).reduce((sum, c) => sum + c.amount, 0);\n return base - lineAllowances + lineCharges;\n}\n\ntype LineType = \"InvoiceLine\" | \"CreditNoteLine\";\ntype QuantityType = \"InvoicedQuantity\" | \"CreditedQuantity\";\n\nfunction buildDocumentLineXml(\n line: InvoiceLine,\n index: number,\n currency: string,\n lineTag: LineType,\n qtyTag: QuantityType,\n): string {\n const lineTotal = calculateLineExtensionAmount(line);\n const unit = resolveUnitCode(line.unit ?? DEFAULT_UNIT);\n const vatCategory = line.vatCategory ?? \"S\";\n\n const lineAllowancesXml = (line.allowances ?? [])\n .map((a) => buildLineAllowanceChargeXml(a.reason, a.amount, false, currency))\n .join(\"\");\n const lineChargesXml = (line.charges ?? [])\n .map((c) => buildLineAllowanceChargeXml(c.reason, c.amount, true, currency))\n .join(\"\");\n\n return `\n <cac:${lineTag}>\n <cbc:ID>${index + 1}</cbc:ID>\n ${line.accountingCost ? `<cbc:AccountingCost>${escapeXml(line.accountingCost)}</cbc:AccountingCost>` : \"\"}\n <cbc:${qtyTag} unitCode=\"${escapeXml(unit)}\">${Number(line.quantity.toFixed(6))}</cbc:${qtyTag}>\n <cbc:LineExtensionAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(lineTotal)}</cbc:LineExtensionAmount>\n ${lineAllowancesXml}${lineChargesXml}\n <cac:Item>\n <cbc:Name>${escapeXml(line.description)}</cbc:Name>\n ${\n line.itemId\n ? `<cac:SellersItemIdentification>\n <cbc:ID>${escapeXml(line.itemId)}</cbc:ID>\n </cac:SellersItemIdentification>`\n : \"\"\n }\n <cac:ClassifiedTaxCategory>\n <cbc:ID>${vatCategory}</cbc:ID>\n <cbc:Percent>${line.vatRate}</cbc:Percent>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:ClassifiedTaxCategory>\n ${\n line.standardItemId\n ? `<cac:StandardItemIdentification>\n <cbc:ID schemeID=\"${escapeXml(line.standardItemScheme ?? \"0160\")}\">${escapeXml(line.standardItemId)}</cbc:ID>\n </cac:StandardItemIdentification>`\n : \"\"\n }\n ${\n line.commodityCode && line.commodityScheme\n ? `<cac:CommodityClassification>\n <cbc:ItemClassificationCode listID=\"${escapeXml(line.commodityScheme)}\">${escapeXml(line.commodityCode)}</cbc:ItemClassificationCode>\n </cac:CommodityClassification>`\n : \"\"\n }\n ${(line.properties ?? []).map(\n (p) => `<cac:AdditionalItemProperty>\n <cbc:Name>${escapeXml(p.name)}</cbc:Name>\n <cbc:Value>${escapeXml(p.value)}</cbc:Value>\n </cac:AdditionalItemProperty>`\n ).join(\"\\n \")}\n </cac:Item>\n <cac:Price>\n <cbc:PriceAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(line.unitPrice)}</cbc:PriceAmount>\n ${line.baseQuantity != null ? `<cbc:BaseQuantity unitCode=\"${escapeXml(resolveUnitCode(line.baseQuantityUnit ?? line.unit ?? DEFAULT_UNIT))}\">${line.baseQuantity}</cbc:BaseQuantity>` : \"\"}\n </cac:Price>\n </cac:${lineTag}>`;\n}\n\nfunction buildInvoiceLineXml(line: InvoiceLine, index: number, currency: string): string {\n return buildDocumentLineXml(line, index, currency, \"InvoiceLine\", \"InvoicedQuantity\");\n}\n\ninterface TaxSubtotal {\n vatRate: number;\n vatCategory: string;\n taxableAmount: number;\n taxAmount: number;\n}\n\nfunction calculateTaxSubtotals(\n lines: InvoiceLine[],\n allowances?: AllowanceCharge[],\n charges?: AllowanceCharge[],\n): TaxSubtotal[] {\n const groups = new Map<string, TaxSubtotal>();\n\n function addToGroup(vatCategory: string, vatRate: number, amount: number) {\n const key = `${vatCategory}-${vatRate}`;\n const lineTax = round2(amount * (vatRate / 100));\n const existing = groups.get(key);\n if (existing) {\n existing.taxableAmount = round2(existing.taxableAmount + amount);\n existing.taxAmount = round2(existing.taxAmount + lineTax);\n } else {\n groups.set(key, {\n vatRate,\n vatCategory,\n taxableAmount: amount,\n taxAmount: lineTax,\n });\n }\n }\n\n for (const line of lines) {\n addToGroup(line.vatCategory ?? \"S\", line.vatRate, calculateLineExtensionAmount(line));\n }\n\n for (const a of allowances ?? []) {\n addToGroup(a.vatCategory ?? \"S\", a.vatRate, -a.amount);\n }\n\n for (const c of charges ?? []) {\n addToGroup(c.vatCategory ?? \"S\", c.vatRate, c.amount);\n }\n\n return Array.from(groups.values());\n}\n\n// ─── Shared document-level XML fragments ───────────────────\n\ninterface DocumentTotals {\n lineExtensionAmount: number;\n allowanceTotalAmount: number;\n chargeTotalAmount: number;\n taxExclusiveAmount: number;\n totalTax: number;\n taxInclusiveAmount: number;\n payableAmount: number;\n taxSubtotals: TaxSubtotal[];\n}\n\nfunction calculateDocumentTotals(\n lines: InvoiceLine[],\n allowances?: AllowanceCharge[],\n charges?: AllowanceCharge[],\n): DocumentTotals {\n const taxSubtotals = calculateTaxSubtotals(lines, allowances, charges);\n const lineExtensionAmount = lines.reduce(\n (sum, line) => sum + calculateLineExtensionAmount(line),\n 0,\n );\n const allowanceTotalAmount = (allowances ?? []).reduce((sum, a) => sum + a.amount, 0);\n const chargeTotalAmount = (charges ?? []).reduce((sum, c) => sum + c.amount, 0);\n const taxExclusiveAmount = round2(lineExtensionAmount - allowanceTotalAmount + chargeTotalAmount);\n const totalTax = round2(taxSubtotals.reduce((sum, st) => sum + st.taxAmount, 0));\n const taxInclusiveAmount = round2(taxExclusiveAmount + totalTax);\n return {\n lineExtensionAmount,\n allowanceTotalAmount,\n chargeTotalAmount,\n taxExclusiveAmount,\n totalTax,\n taxInclusiveAmount,\n payableAmount: taxInclusiveAmount,\n taxSubtotals,\n };\n}\n\nfunction buildTaxTotalXml(taxSubtotals: TaxSubtotal[], totalTax: number, currency: string): string {\n const subtotalsXml = taxSubtotals\n .map(\n (st) => `\n <cac:TaxSubtotal>\n <cbc:TaxableAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(st.taxableAmount)}</cbc:TaxableAmount>\n <cbc:TaxAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(st.taxAmount)}</cbc:TaxAmount>\n <cac:TaxCategory>\n <cbc:ID>${st.vatCategory}</cbc:ID>\n <cbc:Percent>${st.vatRate}</cbc:Percent>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:TaxCategory>\n </cac:TaxSubtotal>`,\n )\n .join(\"\");\n\n return `<cac:TaxTotal>\n <cbc:TaxAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totalTax)}</cbc:TaxAmount>\n ${subtotalsXml}\n </cac:TaxTotal>`;\n}\n\nfunction buildTaxCurrencyTotalXml(totalTax: number, taxCurrency: string, rate: number): string {\n const convertedAmount = Math.round(totalTax * rate * 100) / 100;\n return `<cac:TaxTotal>\n <cbc:TaxAmount currencyID=\"${escapeXml(taxCurrency)}\">${formatAmount(convertedAmount)}</cbc:TaxAmount>\n </cac:TaxTotal>`;\n}\n\ninterface LegalMonetaryTotalOptions {\n prepaidAmount?: number;\n roundingAmount?: number;\n}\n\nfunction buildLegalMonetaryTotalXml(totals: DocumentTotals, currency: string, options?: LegalMonetaryTotalOptions): string {\n const prepaid = options?.prepaidAmount;\n const rounding = options?.roundingAmount;\n const payableAmount = totals.taxInclusiveAmount - (prepaid ?? 0) + (rounding ?? 0);\n\n return `<cac:LegalMonetaryTotal>\n <cbc:LineExtensionAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.lineExtensionAmount)}</cbc:LineExtensionAmount>\n <cbc:TaxExclusiveAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.taxExclusiveAmount)}</cbc:TaxExclusiveAmount>\n <cbc:TaxInclusiveAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.taxInclusiveAmount)}</cbc:TaxInclusiveAmount>\n ${totals.allowanceTotalAmount > 0 ? `<cbc:AllowanceTotalAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.allowanceTotalAmount)}</cbc:AllowanceTotalAmount>` : \"\"}\n ${totals.chargeTotalAmount > 0 ? `<cbc:ChargeTotalAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.chargeTotalAmount)}</cbc:ChargeTotalAmount>` : \"\"}\n ${prepaid != null ? `<cbc:PrepaidAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(prepaid)}</cbc:PrepaidAmount>` : \"\"}\n ${rounding != null ? `<cbc:PayableRoundingAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(rounding)}</cbc:PayableRoundingAmount>` : \"\"}\n <cbc:PayableAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(payableAmount)}</cbc:PayableAmount>\n </cac:LegalMonetaryTotal>`;\n}\n\nfunction buildPaymentMeansXml(input: InvoiceInput | CreditNoteInput): string {\n const paymentMeans = input.paymentMeans ?? DEFAULT_PAYMENT_MEANS;\n return `<cac:PaymentMeans>\n <cbc:PaymentMeansCode>${paymentMeans}</cbc:PaymentMeansCode>\n ${input.paymentReference ? `<cbc:PaymentID>${escapeXml(input.paymentReference)}</cbc:PaymentID>` : \"\"}\n ${\n input.paymentIban\n ? `<cac:PayeeFinancialAccount>\n <cbc:ID>${escapeXml(input.paymentIban)}</cbc:ID>\n ${\n input.paymentBic\n ? `<cac:FinancialInstitutionBranch>\n <cbc:ID>${escapeXml(input.paymentBic)}</cbc:ID>\n </cac:FinancialInstitutionBranch>`\n : \"\"\n }\n </cac:PayeeFinancialAccount>`\n : \"\"\n }\n </cac:PaymentMeans>`;\n}\n\nfunction buildCreditNoteLineXml(line: InvoiceLine, index: number, currency: string): string {\n return buildDocumentLineXml(line, index, currency, \"CreditNoteLine\", \"CreditedQuantity\");\n}\n\nfunction buildOrderReferenceXml(orderReference?: string, salesOrderReference?: string): string {\n if (!orderReference && !salesOrderReference) return \"\";\n const parts: string[] = [\"<cac:OrderReference>\"];\n if (orderReference) {\n parts.push(`<cbc:ID>${escapeXml(orderReference)}</cbc:ID>`);\n }\n if (salesOrderReference) {\n parts.push(`<cbc:SalesOrderID>${escapeXml(salesOrderReference)}</cbc:SalesOrderID>`);\n }\n parts.push(\"</cac:OrderReference>\");\n return parts.join(\"\");\n}\n\n/**\n * Build a Peppol BIS 3.0 compliant UBL 2.1 Invoice XML from a simple JSON input.\n */\nexport function buildInvoiceXml(input: InvoiceInput): string {\n const currency = input.currency ?? \"EUR\";\n const date = formatDate(input.date);\n const dueDate = input.dueDate ? formatDate(input.dueDate) : undefined;\n const hasTaxCurrency = input.taxCurrency && input.taxCurrency !== currency;\n const totals = calculateDocumentTotals(input.lines, input.allowances, input.charges);\n\n const linesXml = input.lines\n .map((line, i) => buildInvoiceLineXml(line, i, currency))\n .join(\"\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Invoice xmlns=\"${UBL_NS}\"\n xmlns:cac=\"${CAC_NS}\"\n xmlns:cbc=\"${CBC_NS}\">\n <cbc:CustomizationID>${PEPPOL_CUSTOMIZATION_ID}</cbc:CustomizationID>\n <cbc:ProfileID>${PEPPOL_PROFILE_ID}</cbc:ProfileID>\n <cbc:ID>${escapeXml(input.number)}</cbc:ID>\n <cbc:IssueDate>${date}</cbc:IssueDate>\n ${dueDate ? `<cbc:DueDate>${dueDate}</cbc:DueDate>` : \"\"}\n ${input.taxPointDate ? `<cbc:TaxPointDate>${formatDate(input.taxPointDate)}</cbc:TaxPointDate>` : \"\"}\n <cbc:InvoiceTypeCode>${input.invoiceTypeCode ?? (input.isCreditNote ? 381 : 380)}</cbc:InvoiceTypeCode>\n ${input.note ? `<cbc:Note>${escapeXml(input.note)}</cbc:Note>` : \"\"}\n ${input.accountingCost ? `<cbc:AccountingCost>${escapeXml(input.accountingCost)}</cbc:AccountingCost>` : \"\"}\n <cbc:DocumentCurrencyCode>${escapeXml(currency)}</cbc:DocumentCurrencyCode>\n ${hasTaxCurrency ? `<cbc:TaxCurrencyCode>${escapeXml(input.taxCurrency!)}</cbc:TaxCurrencyCode>` : \"\"}\n ${input.buyerReference ? `<cbc:BuyerReference>${escapeXml(input.buyerReference)}</cbc:BuyerReference>` : \"\"}\n ${input.invoicePeriod ? buildInvoicePeriodXml(input.invoicePeriod) : \"\"}\n ${buildOrderReferenceXml(input.orderReference, input.salesOrderReference)}\n ${input.despatchReference ? `<cac:DespatchDocumentReference><cbc:ID>${escapeXml(input.despatchReference)}</cbc:ID></cac:DespatchDocumentReference>` : \"\"}\n ${input.receiptReference ? `<cac:ReceiptDocumentReference><cbc:ID>${escapeXml(input.receiptReference)}</cbc:ID></cac:ReceiptDocumentReference>` : \"\"}\n ${input.contractReference ? `<cac:ContractDocumentReference><cbc:ID>${escapeXml(input.contractReference)}</cbc:ID></cac:ContractDocumentReference>` : \"\"}\n ${(input.attachments ?? []).map((a) => buildAttachmentXml(a)).join(\"\\n \")}\n ${input.projectReference ? `<cac:ProjectReference><cbc:ID>${escapeXml(input.projectReference)}</cbc:ID></cac:ProjectReference>` : \"\"}\n ${input.from ? buildPartyXml(input.from, \"AccountingSupplierParty\") : \"\"}\n ${buildPartyXml(input.to, \"AccountingCustomerParty\")}\n ${input.payeeParty ? buildPayeePartyXml(input.payeeParty) : \"\"}\n ${input.taxRepresentative ? buildTaxRepresentativePartyXml(input.taxRepresentative) : \"\"}\n ${input.delivery ? buildDeliveryXml(input.delivery) : \"\"}\n ${buildPaymentMeansXml(input)}\n ${input.paymentTerms ? `<cac:PaymentTerms>\\n <cbc:Note>${escapeXml(input.paymentTerms)}</cbc:Note>\\n </cac:PaymentTerms>` : \"\"}\n ${(input.allowances ?? []).map((a) => buildDocumentAllowanceChargeXml(a, false, currency)).join(\"\")}\n ${(input.charges ?? []).map((c) => buildDocumentAllowanceChargeXml(c, true, currency)).join(\"\")}\n ${hasTaxCurrency && input.taxCurrencyRate ? buildTaxCurrencyTotalXml(totals.totalTax, input.taxCurrency!, input.taxCurrencyRate) : \"\"}\n ${buildTaxTotalXml(totals.taxSubtotals, totals.totalTax, currency)}\n ${buildLegalMonetaryTotalXml(totals, currency, { prepaidAmount: input.prepaidAmount, roundingAmount: input.roundingAmount })}\n ${linesXml}\n</Invoice>`;\n}\n\n/**\n * Build a Peppol BIS 3.0 compliant UBL 2.1 Credit Note XML.\n *\n * Generates XML directly with correct CreditNote elements — no string replacement.\n */\nexport function buildCreditNoteXml(input: CreditNoteInput): string {\n const currency = input.currency ?? \"EUR\";\n const date = formatDate(input.date);\n const dueDate = input.dueDate ? formatDate(input.dueDate) : undefined;\n const hasTaxCurrency = input.taxCurrency && input.taxCurrency !== currency;\n const totals = calculateDocumentTotals(input.lines, input.allowances, input.charges);\n\n const linesXml = input.lines\n .map((line, i) => buildCreditNoteLineXml(line, i, currency))\n .join(\"\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreditNote xmlns=\"${CREDIT_NOTE_NS}\"\n xmlns:cac=\"${CAC_NS}\"\n xmlns:cbc=\"${CBC_NS}\">\n <cbc:CustomizationID>${PEPPOL_CUSTOMIZATION_ID}</cbc:CustomizationID>\n <cbc:ProfileID>${PEPPOL_PROFILE_ID}</cbc:ProfileID>\n <cbc:ID>${escapeXml(input.number)}</cbc:ID>\n <cbc:IssueDate>${date}</cbc:IssueDate>\n ${dueDate ? `<cbc:DueDate>${dueDate}</cbc:DueDate>` : \"\"}\n ${input.taxPointDate ? `<cbc:TaxPointDate>${formatDate(input.taxPointDate)}</cbc:TaxPointDate>` : \"\"}\n <cbc:CreditNoteTypeCode>${input.invoiceTypeCode ?? 381}</cbc:CreditNoteTypeCode>\n ${input.note ? `<cbc:Note>${escapeXml(input.note)}</cbc:Note>` : \"\"}\n ${input.accountingCost ? `<cbc:AccountingCost>${escapeXml(input.accountingCost)}</cbc:AccountingCost>` : \"\"}\n <cbc:DocumentCurrencyCode>${escapeXml(currency)}</cbc:DocumentCurrencyCode>\n ${hasTaxCurrency ? `<cbc:TaxCurrencyCode>${escapeXml(input.taxCurrency!)}</cbc:TaxCurrencyCode>` : \"\"}\n ${input.buyerReference ? `<cbc:BuyerReference>${escapeXml(input.buyerReference)}</cbc:BuyerReference>` : \"\"}\n ${input.invoicePeriod ? buildInvoicePeriodXml(input.invoicePeriod) : \"\"}\n ${buildOrderReferenceXml(input.orderReference, input.salesOrderReference)}\n <cac:BillingReference><cac:InvoiceDocumentReference><cbc:ID>${escapeXml(input.invoiceReference)}</cbc:ID></cac:InvoiceDocumentReference></cac:BillingReference>\n ${input.despatchReference ? `<cac:DespatchDocumentReference><cbc:ID>${escapeXml(input.despatchReference)}</cbc:ID></cac:DespatchDocumentReference>` : \"\"}\n ${input.receiptReference ? `<cac:ReceiptDocumentReference><cbc:ID>${escapeXml(input.receiptReference)}</cbc:ID></cac:ReceiptDocumentReference>` : \"\"}\n ${input.contractReference ? `<cac:ContractDocumentReference><cbc:ID>${escapeXml(input.contractReference)}</cbc:ID></cac:ContractDocumentReference>` : \"\"}\n ${(input.attachments ?? []).map((a) => buildAttachmentXml(a)).join(\"\\n \")}\n ${input.projectReference ? `<cac:ProjectReference><cbc:ID>${escapeXml(input.projectReference)}</cbc:ID></cac:ProjectReference>` : \"\"}\n ${input.from ? buildPartyXml(input.from, \"AccountingSupplierParty\") : \"\"}\n ${buildPartyXml(input.to, \"AccountingCustomerParty\")}\n ${input.payeeParty ? buildPayeePartyXml(input.payeeParty) : \"\"}\n ${input.taxRepresentative ? buildTaxRepresentativePartyXml(input.taxRepresentative) : \"\"}\n ${input.delivery ? buildDeliveryXml(input.delivery) : \"\"}\n ${buildPaymentMeansXml(input)}\n ${input.paymentTerms ? `<cac:PaymentTerms>\\n <cbc:Note>${escapeXml(input.paymentTerms)}</cbc:Note>\\n </cac:PaymentTerms>` : \"\"}\n ${(input.allowances ?? []).map((a) => buildDocumentAllowanceChargeXml(a, false, currency)).join(\"\")}\n ${(input.charges ?? []).map((c) => buildDocumentAllowanceChargeXml(c, true, currency)).join(\"\")}\n ${hasTaxCurrency && input.taxCurrencyRate ? buildTaxCurrencyTotalXml(totals.totalTax, input.taxCurrency!, input.taxCurrencyRate) : \"\"}\n ${buildTaxTotalXml(totals.taxSubtotals, totals.totalTax, currency)}\n ${buildLegalMonetaryTotalXml(totals, currency, { prepaidAmount: input.prepaidAmount, roundingAmount: input.roundingAmount })}\n ${linesXml}\n</CreditNote>`;\n}\n","/**\n * Country-Specific Validation Rules\n *\n * Produces warnings (not blocking errors) for country-specific invoice requirements.\n * Invoices can still be sent, but developers get helpful feedback about\n * local compliance expectations.\n *\n * Each rule has a unique ID: {CC}-{NN} (e.g., BE-01, FR-02).\n */\n\nimport type {\n InvoiceInput,\n ValidationError,\n ValidationWarning,\n} from \"../types/invoice.js\";\n\n// ─── Result Type ─────────────────────────────────────────────\n\nexport interface CountryValidationResult {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────\n\nfunction warn(field: string, message: string, ruleId: string): ValidationWarning {\n return { field, message, ruleId };\n}\n\n// ─── Belgium (BE) ────────────────────────────────────────────\n\n/**\n * Belgian structured communication format: +++NNN/NNNN/NNNNN+++\n * The last 2 of the 12 digits are a mod-97 check digit.\n * If base mod 97 === 0, the check digit is 97.\n */\nconst BE_STRUCTURED_RE = /^\\+{3}\\d{3}\\/\\d{4}\\/\\d{5}\\+{3}$/;\n\nfunction validateBelgianCheckDigit(reference: string): boolean {\n // Extract the 12 digits from +++NNN/NNNN/NNNNN+++\n const digits = reference.replace(/[^0-9]/g, \"\");\n if (digits.length !== 12) return false;\n\n const base = parseInt(digits.slice(0, 10), 10);\n const check = parseInt(digits.slice(10, 12), 10);\n const expected = base % 97 === 0 ? 97 : base % 97;\n\n return check === expected;\n}\n\nfunction validateBelgium(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const ref = input.paymentReference;\n\n if (ref && BE_STRUCTURED_RE.test(ref)) {\n // It's in structured format — verify the checksum\n if (!validateBelgianCheckDigit(ref)) {\n warnings.push(\n warn(\n \"paymentReference\",\n `Belgian structured communication \"${ref}\" has an invalid mod-97 checksum. Verify the reference.`,\n \"BE-01\",\n ),\n );\n }\n } else if (!ref) {\n warnings.push(\n warn(\n \"paymentReference\",\n \"Belgian recipients typically expect a structured communication reference (+++NNN/NNNN/NNNNN+++ format).\",\n \"BE-02\",\n ),\n );\n }\n}\n\n/**\n * Seller-direction Belgian rules: only payment reference validation.\n * Separated from validateBelgium() to prevent buyer-focused rules\n * from accidentally firing with buyer data in a seller context.\n */\nfunction validateBelgiumSeller(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const ref = input.paymentReference;\n\n if (ref && BE_STRUCTURED_RE.test(ref)) {\n if (!validateBelgianCheckDigit(ref)) {\n warnings.push(\n warn(\n \"paymentReference\",\n `Belgian structured communication \"${ref}\" has an invalid mod-97 checksum. Verify the reference.`,\n \"BE-01\",\n ),\n );\n }\n } else if (!ref) {\n warnings.push(\n warn(\n \"paymentReference\",\n \"Belgian sellers typically include a structured communication reference (+++NNN/NNNN/NNNNN+++ format).\",\n \"BE-02\",\n ),\n );\n }\n}\n\n// ─── France (FR) ─────────────────────────────────────────────\n\nconst FR_SIRET_RE = /^\\d{14}$/;\nconst FR_VAT_RE = /^FR[A-Z0-9]{2}\\d{9}$/;\n\nfunction validateFrance(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const { companyId, vatNumber } = input.to ?? {};\n\n if (companyId && !FR_SIRET_RE.test(companyId)) {\n warnings.push(\n warn(\n \"to.companyId\",\n `French company ID (SIRET) should be exactly 14 digits, got \"${companyId}\".`,\n \"FR-01\",\n ),\n );\n }\n\n if (vatNumber && !FR_VAT_RE.test(vatNumber)) {\n warnings.push(\n warn(\n \"to.vatNumber\",\n `French VAT number should match format FR + 2 characters + 9 digits (SIREN), got \"${vatNumber}\".`,\n \"FR-02\",\n ),\n );\n }\n}\n\n// ─── Italy (IT) ──────────────────────────────────────────────\n\nfunction validateItaly(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n if (!input.buyerReference) {\n warnings.push(\n warn(\n \"buyerReference\",\n \"Italian recipients (SDI) typically require a buyer reference (CIG/CUP code). Consider setting buyerReference.\",\n \"IT-01\",\n ),\n );\n }\n\n const peppolId = input.to?.peppolId;\n if (peppolId?.startsWith(\"0201:\")) {\n const fiscalCode = peppolId.slice(5);\n if (fiscalCode.length !== 11 && fiscalCode.length !== 16) {\n warnings.push(\n warn(\n \"to.peppolId\",\n `Italian fiscal code (after 0201:) should be 11 digits (partita IVA) or 16 characters (codice fiscale), got ${fiscalCode.length} characters.`,\n \"IT-02\",\n ),\n );\n }\n }\n}\n\n// ─── Netherlands (NL) ───────────────────────────────────────\n\nconst NL_KVK_RE = /^\\d{8}$/;\nconst NL_VAT_RE = /^NL\\d{9}B\\d{2}$/;\n\nfunction validateNetherlands(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const { companyId, vatNumber } = input.to ?? {};\n\n if (companyId && !NL_KVK_RE.test(companyId)) {\n warnings.push(\n warn(\n \"to.companyId\",\n `Dutch KVK number should be exactly 8 digits, got \"${companyId}\".`,\n \"NL-01\",\n ),\n );\n }\n\n if (vatNumber && !NL_VAT_RE.test(vatNumber)) {\n warnings.push(\n warn(\n \"to.vatNumber\",\n `Dutch VAT number should match format NL + 9 digits + B + 2 digits, got \"${vatNumber}\".`,\n \"NL-02\",\n ),\n );\n }\n}\n\n// ─── Germany (DE) ────────────────────────────────────────────\n\nconst DE_VAT_RE = /^DE\\d{9}$/;\n\nfunction validateGermany(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const { vatNumber } = input.to ?? {};\n\n if (vatNumber && !DE_VAT_RE.test(vatNumber)) {\n warnings.push(\n warn(\n \"to.vatNumber\",\n `German VAT number should match format DE + 9 digits, got \"${vatNumber}\".`,\n \"DE-01\",\n ),\n );\n }\n}\n\n// ─── Main Entry Point ───────────────────────────────────────\n\n/**\n * Validate country-specific rules for an invoice.\n *\n * Returns warnings for common compliance issues specific to the\n * recipient's country. These are advisory — the invoice can still be sent.\n *\n * @example\n * ```ts\n * const result = validateCountryRules(invoice);\n * for (const w of result.warnings) {\n * console.warn(`[${w.ruleId}] ${w.field}: ${w.message}`);\n * }\n * ```\n */\nexport function validateCountryRules(input: InvoiceInput): CountryValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n const buyerCountry = input.to?.country;\n const sellerCountry = input.from?.country;\n\n // Buyer-country rules\n if (buyerCountry) {\n switch (buyerCountry) {\n case \"BE\": validateBelgium(input, errors, warnings); break;\n case \"FR\": validateFrance(input, errors, warnings); break;\n case \"IT\": validateItaly(input, errors, warnings); break;\n case \"NL\": validateNetherlands(input, errors, warnings); break;\n case \"DE\": validateGermany(input, errors, warnings); break;\n }\n }\n\n // Seller-country rules (skip if same as buyer to avoid duplicates)\n if (sellerCountry && sellerCountry !== buyerCountry) {\n switch (sellerCountry) {\n case \"BE\": validateBelgiumSeller(input, errors, warnings); break;\n }\n }\n\n return { errors, warnings };\n}\n","/**\n * Peppol Code Lists — Static lookup utilities\n *\n * Provides tree-shakeable helper functions for common Peppol-related code lists:\n * countries, EAS schemes, unit codes, VAT categories, and payment means.\n *\n * All data is static — no API calls, no side effects.\n */\n\n// ─── Countries (ISO 3166-1 alpha-2) ───────────────────────────────────────────\n\n/** EU + EEA + common Peppol trading partners (~50 most used) */\nconst COUNTRIES: ReadonlyMap<string, string> = new Map([\n // EU member states\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 [\"IE\", \"Ireland\"],\n [\"IT\", \"Italy\"],\n [\"LV\", \"Latvia\"],\n [\"LT\", \"Lithuania\"],\n [\"LU\", \"Luxembourg\"],\n [\"MT\", \"Malta\"],\n [\"NL\", \"Netherlands\"],\n [\"PL\", \"Poland\"],\n [\"PT\", \"Portugal\"],\n [\"RO\", \"Romania\"],\n [\"SK\", \"Slovakia\"],\n [\"SI\", \"Slovenia\"],\n [\"ES\", \"Spain\"],\n [\"SE\", \"Sweden\"],\n // EEA (non-EU)\n [\"IS\", \"Iceland\"],\n [\"LI\", \"Liechtenstein\"],\n [\"NO\", \"Norway\"],\n // Common Peppol trading partners\n [\"GB\", \"United Kingdom\"],\n [\"CH\", \"Switzerland\"],\n [\"US\", \"United States\"],\n [\"CA\", \"Canada\"],\n [\"AU\", \"Australia\"],\n [\"NZ\", \"New Zealand\"],\n [\"SG\", \"Singapore\"],\n [\"JP\", \"Japan\"],\n [\"KR\", \"South Korea\"],\n [\"IN\", \"India\"],\n [\"TR\", \"Turkey\"],\n [\"SA\", \"Saudi Arabia\"],\n [\"AE\", \"United Arab Emirates\"],\n [\"IL\", \"Israel\"],\n [\"ZA\", \"South Africa\"],\n [\"BR\", \"Brazil\"],\n [\"MX\", \"Mexico\"],\n [\"MY\", \"Malaysia\"],\n [\"TH\", \"Thailand\"],\n [\"ID\", \"Indonesia\"],\n]);\n\n/**\n * Get the country name for an ISO 3166-1 alpha-2 code.\n *\n * @param code - Two-letter country code (case-insensitive)\n * @returns Country name or `undefined` if not found\n *\n * @example\n * ```ts\n * getCountryName(\"FR\") // \"France\"\n * getCountryName(\"XX\") // undefined\n * ```\n */\nexport function getCountryName(code: string): string | undefined {\n return COUNTRIES.get(code.toUpperCase());\n}\n\n/**\n * Get all supported countries.\n *\n * @returns Array of `{ code, name }` objects sorted by name\n */\nexport function getAllCountries(): Array<{ code: string; name: string }> {\n return Array.from(COUNTRIES.entries())\n .map(([code, name]) => ({ code, name }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n// ─── Currencies (ISO 4217) ────────────────────────────────────────────────────\n\n/**\n * A currency entry per ISO 4217.\n */\nexport interface Currency {\n /** Three-letter ISO 4217 code (uppercase) */\n code: string;\n /** Currency name */\n name: string;\n /** Standard minor unit count (e.g., 2 for EUR, 0 for JPY, 3 for BHD) */\n minorUnits: number;\n}\n\n/** Common Peppol/EU trade currencies (~30 most used) */\nconst CURRENCIES: ReadonlyMap<string, Currency> = new Map([\n [\"EUR\", { code: \"EUR\", name: \"Euro\", minorUnits: 2 }],\n [\"USD\", { code: \"USD\", name: \"US Dollar\", minorUnits: 2 }],\n [\"GBP\", { code: \"GBP\", name: \"Pound Sterling\", minorUnits: 2 }],\n [\"CHF\", { code: \"CHF\", name: \"Swiss Franc\", minorUnits: 2 }],\n [\"DKK\", { code: \"DKK\", name: \"Danish Krone\", minorUnits: 2 }],\n [\"NOK\", { code: \"NOK\", name: \"Norwegian Krone\", minorUnits: 2 }],\n [\"SEK\", { code: \"SEK\", name: \"Swedish Krona\", minorUnits: 2 }],\n [\"PLN\", { code: \"PLN\", name: \"Polish Zloty\", minorUnits: 2 }],\n [\"CZK\", { code: \"CZK\", name: \"Czech Koruna\", minorUnits: 2 }],\n [\"HUF\", { code: \"HUF\", name: \"Hungarian Forint\", minorUnits: 2 }],\n [\"RON\", { code: \"RON\", name: \"Romanian Leu\", minorUnits: 2 }],\n [\"BGN\", { code: \"BGN\", name: \"Bulgarian Lev\", minorUnits: 2 }],\n [\"HRK\", { code: \"HRK\", name: \"Croatian Kuna\", minorUnits: 2 }],\n [\"ISK\", { code: \"ISK\", name: \"Icelandic Krona\", minorUnits: 0 }],\n [\"TRY\", { code: \"TRY\", name: \"Turkish Lira\", minorUnits: 2 }],\n [\"JPY\", { code: \"JPY\", name: \"Japanese Yen\", minorUnits: 0 }],\n [\"CNY\", { code: \"CNY\", name: \"Chinese Yuan\", minorUnits: 2 }],\n [\"KRW\", { code: \"KRW\", name: \"South Korean Won\", minorUnits: 0 }],\n [\"INR\", { code: \"INR\", name: \"Indian Rupee\", minorUnits: 2 }],\n [\"SGD\", { code: \"SGD\", name: \"Singapore Dollar\", minorUnits: 2 }],\n [\"AUD\", { code: \"AUD\", name: \"Australian Dollar\", minorUnits: 2 }],\n [\"NZD\", { code: \"NZD\", name: \"New Zealand Dollar\", minorUnits: 2 }],\n [\"CAD\", { code: \"CAD\", name: \"Canadian Dollar\", minorUnits: 2 }],\n [\"BRL\", { code: \"BRL\", name: \"Brazilian Real\", minorUnits: 2 }],\n [\"MXN\", { code: \"MXN\", name: \"Mexican Peso\", minorUnits: 2 }],\n [\"ZAR\", { code: \"ZAR\", name: \"South African Rand\", minorUnits: 2 }],\n [\"AED\", { code: \"AED\", name: \"UAE Dirham\", minorUnits: 2 }],\n [\"SAR\", { code: \"SAR\", name: \"Saudi Riyal\", minorUnits: 2 }],\n [\"ILS\", { code: \"ILS\", name: \"Israeli Shekel\", minorUnits: 2 }],\n [\"HKD\", { code: \"HKD\", name: \"Hong Kong Dollar\", minorUnits: 2 }],\n [\"TWD\", { code: \"TWD\", name: \"Taiwan Dollar\", minorUnits: 2 }],\n]);\n\n/**\n * Look up a currency by ISO 4217 code.\n *\n * @param code - Three-letter currency code (case-insensitive)\n * @returns The currency entry or `undefined` if not found\n *\n * @example\n * ```ts\n * getCurrency(\"EUR\") // { code: \"EUR\", name: \"Euro\", minorUnits: 2 }\n * getCurrency(\"eu\") // undefined\n * ```\n */\nexport function getCurrency(code: string): Currency | undefined {\n return CURRENCIES.get(code.toUpperCase());\n}\n\n/**\n * Get all supported currencies.\n *\n * @returns Array sorted by ISO code ascending\n */\nexport function getAllCurrencies(): Currency[] {\n return Array.from(CURRENCIES.values()).sort((a, b) => a.code.localeCompare(b.code));\n}\n\n// ─── EAS Schemes (Peppol participant identifier schemes) ──────────────────────\n\n/**\n * A Peppol Electronic Address Scheme (EAS) entry.\n */\nexport interface EasScheme {\n /** Numeric EAS code (e.g. \"0088\") */\n code: string;\n /** Human-readable scheme name */\n name: string;\n /** ISO country code if scheme is country-specific */\n country?: string;\n}\n\nconst EAS_SCHEMES: readonly EasScheme[] = [\n { code: \"0002\", name: \"System Information et Repertoire des Entreprises et des Etablissements (SIRENE)\", country: \"FR\" },\n { code: \"0007\", name: \"Organisationsnummer\", country: \"SE\" },\n { code: \"0009\", name: \"SIRET-CODE\", country: \"FR\" },\n { code: \"0088\", name: \"EAN Location Code (GLN)\" },\n { code: \"0096\", name: \"Danish Chamber of Commerce (P-nummer)\", country: \"DK\" },\n { code: \"0184\", name: \"Danish Central Business Register (CVR)\", country: \"DK\" },\n { code: \"0190\", name: \"Dutch Chamber of Commerce (KVK)\", country: \"NL\" },\n { code: \"0191\", name: \"Organisatie Identificatie Nummer (OIN)\", country: \"NL\" },\n { code: \"0192\", name: \"Danish SE-number (Erhvervsstyrelsen)\", country: \"DK\" },\n { code: \"0195\", name: \"Singapore Unique Entity Number (UEN)\", country: \"SG\" },\n { code: \"0196\", name: \"Icelandic Kennitala\", country: \"IS\" },\n { code: \"0198\", name: \"Danish ERST id (Erhvervsstyrelsen)\", country: \"DK\" },\n { code: \"0200\", name: \"Lithuanian Legal Entity Register (GRIS)\", country: \"LT\" },\n { code: \"0201\", name: \"Italian Codice Destinatario\", country: \"IT\" },\n { code: \"0202\", name: \"Italian Fiscal Code (Codice Fiscale)\", country: \"IT\" },\n { code: \"0204\", name: \"German Leitweg-ID\", country: \"DE\" },\n { code: \"0208\", name: \"Belgian Enterprise Number (KBO/BCE)\", country: \"BE\" },\n { code: \"0209\", name: \"German Creditor Identifier (GS1)\", country: \"DE\" },\n { code: \"0210\", name: \"Italian Codice Fiscale (per IPA)\", country: \"IT\" },\n { code: \"0211\", name: \"Italian Partita IVA (VAT number)\", country: \"IT\" },\n { code: \"0212\", name: \"Finnish OVT code\", country: \"FI\" },\n { code: \"0213\", name: \"Finnish OP identifier\", country: \"FI\" },\n { code: \"0225\", name: \"FRCTC Electronic Address\", country: \"FR\" },\n { code: \"9957\", name: \"French VAT number\", country: \"FR\" },\n] as const;\n\n/** Lookup index: EAS code → scheme */\nconst EAS_BY_CODE: ReadonlyMap<string, EasScheme> = new Map(\n EAS_SCHEMES.map((s) => [s.code, s]),\n);\n\n/**\n * Look up an EAS scheme by its numeric code.\n *\n * @param code - EAS code (e.g. \"0088\", \"0208\")\n * @returns The scheme or `undefined` if not found\n *\n * @example\n * ```ts\n * getEasScheme(\"0208\") // { code: \"0208\", name: \"Belgian Enterprise Number (KBO/BCE)\", country: \"BE\" }\n * getEasScheme(\"9999\") // undefined\n * ```\n */\nexport function getEasScheme(code: string): EasScheme | undefined {\n return EAS_BY_CODE.get(code);\n}\n\n/**\n * Get all known EAS schemes.\n *\n * @returns Array of EAS schemes sorted by code\n */\nexport function getAllEasSchemes(): EasScheme[] {\n return [...EAS_SCHEMES];\n}\n\n// ─── Unit Codes (UN/ECE Recommendation 20) ────────────────────────────────────\n\n/** Human-readable aliases → UN/ECE unit codes */\nconst UNIT_ALIAS_MAP: Record<string, string> = {\n each: \"EA\", piece: \"EA\", pieces: \"EA\",\n hour: \"HUR\", hours: \"HUR\",\n day: \"DAY\", days: \"DAY\",\n week: \"WEE\", weeks: \"WEE\",\n month: \"MON\", months: \"MON\",\n year: \"ANN\", years: \"ANN\",\n kilogram: \"KGM\", kg: \"KGM\",\n meter: \"MTR\", metre: \"MTR\",\n liter: \"LTR\", litre: \"LTR\",\n unit: \"C62\", units: \"C62\",\n set: \"SET\", sets: \"SET\",\n pack: \"PK\", packs: \"PK\",\n minute: \"MIN\", minutes: \"MIN\",\n second: \"SEC\", seconds: \"SEC\",\n tonne: \"TNE\", ton: \"TNE\",\n \"square metre\": \"MTK\", \"square meter\": \"MTK\", sqm: \"MTK\",\n};\n\n/** Canonical unit codes with human-readable names */\nconst UNIT_CODES: ReadonlyMap<string, string> = new Map([\n [\"EA\", \"Each\"],\n [\"HUR\", \"Hour\"],\n [\"DAY\", \"Day\"],\n [\"WEE\", \"Week\"],\n [\"MON\", \"Month\"],\n [\"ANN\", \"Year\"],\n [\"MIN\", \"Minute\"],\n [\"SEC\", \"Second\"],\n [\"KGM\", \"Kilogram\"],\n [\"MTR\", \"Metre\"],\n [\"LTR\", \"Litre\"],\n [\"MTK\", \"Square metre\"],\n [\"TNE\", \"Tonne\"],\n [\"C62\", \"One (unit)\"],\n [\"SET\", \"Set\"],\n [\"PK\", \"Pack\"],\n]);\n\n/**\n * Resolve a human-readable unit name or alias to its UN/ECE Recommendation 20 code.\n *\n * Accepts both aliases (\"hours\", \"kg\") and canonical codes (\"HUR\", \"KGM\").\n * Unknown values pass through unchanged.\n *\n * @param input - Unit name or code\n * @returns Resolved UN/ECE code\n *\n * @example\n * ```ts\n * resolveUnit(\"hours\") // \"HUR\"\n * resolveUnit(\"HUR\") // \"HUR\"\n * resolveUnit(\"kg\") // \"KGM\"\n * resolveUnit(\"XYZ\") // \"XYZ\" (passthrough)\n * ```\n */\nexport function resolveUnit(input: string): string {\n return UNIT_ALIAS_MAP[input.toLowerCase()] ?? input;\n}\n\n/**\n * Get all supported unit codes with human-readable names.\n *\n * @returns Array of `{ code, name }` objects sorted by code\n */\nexport function getAllUnits(): Array<{ code: string; name: string }> {\n return Array.from(UNIT_CODES.entries())\n .map(([code, name]) => ({ code, name }))\n .sort((a, b) => a.code.localeCompare(b.code));\n}\n\n// ─── VAT Categories (UNCL 5305) ──────────────────────────────────────────────\n\n/**\n * A Peppol VAT category entry.\n */\nexport interface VatCategory {\n /** Category code (e.g. \"S\", \"Z\", \"AE\") */\n code: string;\n /** Short name */\n name: string;\n /** Longer description */\n description: string;\n}\n\nconst VAT_CATEGORIES: readonly VatCategory[] = [\n { code: \"S\", name: \"Standard rate\", description: \"Standard VAT rate applies\" },\n { code: \"Z\", name: \"Zero rated\", description: \"Zero-rated goods — VAT at 0% but right to deduct input VAT\" },\n { code: \"E\", name: \"Exempt\", description: \"Exempt from VAT — no right to deduct input VAT\" },\n { code: \"AE\", name: \"Reverse charge\", description: \"VAT reverse charge — customer accounts for VAT\" },\n { code: \"K\", name: \"Intra-community supply\", description: \"Intra-community supply of goods — exempt with right to deduct\" },\n { code: \"G\", name: \"Export outside the EU\", description: \"Free export item — tax not charged\" },\n { code: \"O\", name: \"Outside scope of VAT\", description: \"Services outside scope of VAT\" },\n { code: \"L\", name: \"Canary Islands IGIC\", description: \"Canary Islands general indirect tax (IGIC)\" },\n { code: \"M\", name: \"Ceuta and Melilla IPSI\", description: \"Tax for production, services and importation in Ceuta and Melilla (IPSI)\" },\n] as const;\n\n/**\n * Get all Peppol VAT category codes.\n *\n * @returns Array of VAT categories\n */\nexport function getVatCategories(): VatCategory[] {\n return [...VAT_CATEGORIES];\n}\n\n// ─── Payment Means (UNCL 4461) ───────────────────────────────────────────────\n\n/**\n * A payment means code entry.\n */\nexport interface PaymentMeansCode {\n /** Numeric code */\n code: number;\n /** Human-readable description */\n name: string;\n}\n\nconst PAYMENT_MEANS_CODES: readonly PaymentMeansCode[] = [\n { code: 10, name: \"Cash\" },\n { code: 20, name: \"Cheque\" },\n { code: 30, name: \"Credit transfer\" },\n { code: 42, name: \"Payment to bank account\" },\n { code: 48, name: \"Bank card\" },\n { code: 49, name: \"Direct debit\" },\n { code: 57, name: \"Standing agreement\" },\n { code: 58, name: \"SEPA credit transfer\" },\n { code: 59, name: \"SEPA direct debit\" },\n] as const;\n\n/**\n * Get all supported payment means codes.\n *\n * @returns Array of payment means codes sorted by code\n */\nexport function getPaymentMeansCodes(): PaymentMeansCode[] {\n return [...PAYMENT_MEANS_CODES];\n}\n","/**\n * Invoice Validator\n *\n * Validates invoice data BEFORE conversion to XML.\n * Implements key Peppol BIS 3.0 business rules with human-readable error messages.\n *\n * Design principle: Errors tell you WHAT's wrong, WHERE it is, and HOW to fix it.\n * No developer should need to Google a Peppol rule ID.\n */\n\nimport type {\n InvoiceInput,\n InvoiceLine,\n Party,\n ValidationResult,\n ValidationError,\n ValidationWarning,\n} from \"../types/invoice.js\";\nimport { validateCountryRules } from \"./country-rules.js\";\nimport { getCurrency } from \"./code-lists.js\";\n\nfunction error(field: string, message: string, ruleId?: string, suggestion?: string): ValidationError {\n return { field, message, ruleId, suggestion };\n}\n\nfunction warning(field: string, message: string, ruleId?: string): ValidationWarning {\n return { field, message, ruleId };\n}\n\n/**\n * Type-guard that pushes a clean ValidationError when value is not a string.\n * Returns false to signal that downstream string-only checks should be skipped.\n * Prevents raw TypeError bubbling out of the SDK on malformed input (GPR-414 #3).\n */\nfunction assertString(\n value: unknown,\n fieldPath: string,\n errors: ValidationError[],\n): value is string {\n if (typeof value !== \"string\") {\n errors.push(error(\n fieldPath,\n `Expected string, received ${value === null ? \"null\" : typeof value}`,\n undefined,\n \"Check your payload — this field must be a text value\",\n ));\n return false;\n }\n return true;\n}\n\nconst ISO_DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nfunction validateParty(party: Party, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (party.name === undefined || party.name === null || party.name === \"\") {\n errors.push(error(`${path}.name`, \"Business name is required\", \"BR-06\"));\n } else if (!assertString(party.name, `${path}.name`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.name.trim()) {\n errors.push(error(`${path}.name`, \"Business name is required\", \"BR-06\"));\n }\n\n if (party.peppolId === undefined || party.peppolId === null || (party.peppolId as string) === \"\") {\n errors.push(\n error(\n `${path}.peppolId`,\n \"Peppol participant ID is required\",\n undefined,\n 'Format: \"scheme:id\", e.g. \"0208:0685660237\" for Belgian companies'\n )\n );\n } else if (!assertString(party.peppolId, `${path}.peppolId`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.peppolId.includes(\":\")) {\n errors.push(\n error(\n `${path}.peppolId`,\n `Invalid Peppol ID format: \"${party.peppolId}\"`,\n undefined,\n 'Must be \"scheme:id\" format. Common schemes: 0208 (Belgium), 0009 (France SIRET), 0204 (Germany Leitweg)'\n )\n );\n }\n\n if (party.country === undefined || party.country === null || party.country === \"\") {\n errors.push(error(`${path}.country`, \"Country code is required\", \"BR-11\"));\n } else if (!assertString(party.country, `${path}.country`, errors)) {\n // skip — assertString already pushed the type error\n } else if (party.country.length !== 2) {\n errors.push(\n error(\n `${path}.country`,\n `Invalid country code: \"${party.country}\"`,\n undefined,\n \"Must be ISO 3166-1 alpha-2 (e.g., BE, FR, DE, NL)\"\n )\n );\n }\n\n return errors;\n}\n\n/** Validate buyer postal address — required by Peppol BIS 3.0 (BG-8) and Storecove */\nfunction validateBuyerAddress(party: Party, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (party.street === undefined || party.street === null || party.street === \"\") {\n errors.push(error(`${path}.street`, \"Street address is required for the buyer\", \"BR-50\",\n 'e.g. \"123 Business Street\"'));\n } else if (!assertString(party.street, `${path}.street`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.street.trim()) {\n errors.push(error(`${path}.street`, \"Street address is required for the buyer\", \"BR-50\",\n 'e.g. \"123 Business Street\"'));\n }\n\n if (party.city === undefined || party.city === null || party.city === \"\") {\n errors.push(error(`${path}.city`, \"City is required for the buyer\", \"BR-51\",\n 'e.g. \"Brussels\"'));\n } else if (!assertString(party.city, `${path}.city`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.city.trim()) {\n errors.push(error(`${path}.city`, \"City is required for the buyer\", \"BR-51\",\n 'e.g. \"Brussels\"'));\n }\n\n if (party.postalCode === undefined || party.postalCode === null || party.postalCode === \"\") {\n errors.push(error(`${path}.postalCode`, \"Postal code is required for the buyer\", \"BR-53\",\n 'e.g. \"1000\"'));\n } else if (!assertString(party.postalCode, `${path}.postalCode`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.postalCode.trim()) {\n errors.push(error(`${path}.postalCode`, \"Postal code is required for the buyer\", \"BR-53\",\n 'e.g. \"1000\"'));\n }\n\n return errors;\n}\n\nfunction validateLine(line: InvoiceLine, index: number, isCreditNote = false): ValidationError[] {\n const errors: ValidationError[] = [];\n const path = `lines[${index}]`;\n\n if (line.description === undefined || line.description === null || line.description === \"\") {\n errors.push(error(`${path}.description`, \"Line item description is required\", \"BR-25\"));\n } else if (!assertString(line.description, `${path}.description`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!line.description.trim()) {\n errors.push(error(`${path}.description`, \"Line item description is required\", \"BR-25\"));\n }\n\n if (line.quantity === undefined || line.quantity === null) {\n errors.push(error(`${path}.quantity`, \"Quantity is required\", \"BR-22\"));\n } else if (line.quantity <= 0 && !isCreditNote) {\n errors.push(\n error(\n `${path}.quantity`,\n `Quantity must be positive, got ${line.quantity}`,\n undefined,\n \"For returns/credits, use a credit note instead\"\n )\n );\n }\n\n if (line.unitPrice === undefined || line.unitPrice === null) {\n errors.push(error(`${path}.unitPrice`, \"Unit price is required\", \"BR-26\"));\n } else if (line.unitPrice < 0) {\n errors.push(\n error(\n `${path}.unitPrice`,\n `Unit price cannot be negative, got ${line.unitPrice}`,\n undefined,\n \"For discounts, use a negative quantity or a separate discount line\"\n )\n );\n }\n\n if (line.vatRate === undefined || line.vatRate === null) {\n errors.push(error(`${path}.vatRate`, \"VAT rate is required\", \"BR-CO-17\"));\n } else if (line.vatRate < 0 || line.vatRate > 100) {\n errors.push(\n error(\n `${path}.vatRate`,\n `VAT rate must be between 0 and 100, got ${line.vatRate}`,\n undefined,\n \"Use 0 for zero-rated, 21 for standard Belgian VAT, etc.\"\n )\n );\n }\n\n return errors;\n}\n\n/**\n * Validate an invoice input before sending.\n * Returns human-readable errors with suggestions for fixes.\n */\nexport function validateInvoice(input: InvoiceInput): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // ── Invoice-level validation ──\n\n if (input.number === undefined || input.number === null || input.number === \"\") {\n errors.push(\n error(\"number\", \"Invoice number is required\", \"BR-02\", \"Must be unique per supplier\")\n );\n } else if (!assertString(input.number, \"number\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!input.number.trim()) {\n errors.push(\n error(\"number\", \"Invoice number is required\", \"BR-02\", \"Must be unique per supplier\")\n );\n }\n\n // ── Invoice type code validation ──\n\n const VALID_TYPE_CODES = [380, 381, 383, 384, 386, 389, 751];\n if (input.invoiceTypeCode != null && !VALID_TYPE_CODES.includes(input.invoiceTypeCode)) {\n errors.push(\n error(\n \"invoiceTypeCode\",\n `Invalid invoice type code: ${input.invoiceTypeCode}`,\n undefined,\n \"Valid codes: 380, 381, 383, 384, 386, 389, 751\"\n )\n );\n }\n\n // ── Credit note validation ──\n\n if (input.isCreditNote) {\n const ref = input.invoiceReference;\n if (ref === undefined || ref === null || ref === \"\") {\n errors.push(error(\n \"invoiceReference\",\n \"Reference to the original invoice is required for credit notes\",\n undefined,\n 'Set invoiceReference to the original invoice number (e.g., \"INV-001\")'\n ));\n } else if (!assertString(ref, \"invoiceReference\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!ref.trim()) {\n errors.push(error(\n \"invoiceReference\",\n \"Reference to the original invoice is required for credit notes\",\n undefined,\n 'Set invoiceReference to the original invoice number (e.g., \"INV-001\")'\n ));\n }\n }\n\n if (input.from) {\n warnings.push(\n warning(\n \"from\",\n \"Seller info is determined by your API key. The 'from' field is deprecated and ignored.\",\n )\n );\n }\n\n if (!input.to) {\n errors.push(error(\"to\", \"Buyer (to) is required\", \"BR-07\"));\n } else {\n errors.push(...validateParty(input.to, \"to\"));\n errors.push(...validateBuyerAddress(input.to, \"to\"));\n }\n\n if (input.payeeParty) {\n const ppName = input.payeeParty.name;\n if (ppName === undefined || ppName === null || ppName === \"\") {\n errors.push(error(\"payeeParty.name\", \"Payee party name is required\", \"BR-17\"));\n } else if (!assertString(ppName, \"payeeParty.name\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!ppName.trim()) {\n errors.push(error(\"payeeParty.name\", \"Payee party name is required\", \"BR-17\"));\n }\n\n const ppId = input.payeeParty.peppolId;\n if (ppId === undefined || ppId === null || (ppId as string) === \"\") {\n errors.push(\n error(\n \"payeeParty.peppolId\",\n \"Payee party Peppol ID is required\",\n undefined,\n 'Format: \"scheme:id\", e.g. \"0208:0685660237\"'\n )\n );\n } else if (!assertString(ppId, \"payeeParty.peppolId\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!ppId.includes(\":\")) {\n errors.push(\n error(\n \"payeeParty.peppolId\",\n `Invalid Peppol ID format: \"${ppId}\"`,\n undefined,\n 'Must be \"scheme:id\" format'\n )\n );\n }\n }\n\n if (!input.lines || input.lines.length === 0) {\n errors.push(\n error(\"lines\", \"At least one line item is required\", \"BR-16\", \"Add items to the lines array\")\n );\n } else {\n for (let i = 0; i < input.lines.length; i++) {\n errors.push(...validateLine(input.lines[i]!, i, input.isCreditNote));\n }\n }\n\n // ── Date validation ──\n\n if (input.date) {\n if (!ISO_DATE_RE.test(input.date)) {\n errors.push(\n error(\"date\", `Invalid date format: \"${input.date}\"`, undefined, \"Use ISO 8601: YYYY-MM-DD\")\n );\n }\n }\n\n if (input.dueDate) {\n if (!ISO_DATE_RE.test(input.dueDate)) {\n errors.push(\n error(\n \"dueDate\",\n `Invalid due date format: \"${input.dueDate}\"`,\n undefined,\n \"Use ISO 8601: YYYY-MM-DD\"\n )\n );\n }\n }\n\n // ── TaxPointDate validation (BT-7) ──\n\n if (input.taxPointDate) {\n if (!ISO_DATE_RE.test(input.taxPointDate)) {\n errors.push(\n error(\n \"taxPointDate\",\n `Invalid tax point date format: \"${input.taxPointDate}\"`,\n undefined,\n \"Use ISO 8601: YYYY-MM-DD\"\n )\n );\n }\n }\n\n // ── RoundingAmount validation (BT-114) ──\n\n if (input.roundingAmount !== undefined && input.roundingAmount !== null) {\n if (input.roundingAmount < -0.99 || input.roundingAmount > 0.99) {\n errors.push(\n error(\n \"roundingAmount\",\n `Rounding amount must be between -0.99 and 0.99, got ${input.roundingAmount}`,\n undefined,\n \"B2BRouter stores rounding as integer cents (±99). Use values like 0.50 or -0.25.\"\n )\n );\n }\n }\n\n // ── BuyerReference / OrderReference (BT-10) ──\n\n if (!input.buyerReference && !input.orderReference) {\n warnings.push(\n warning(\n \"buyerReference\",\n \"Either buyerReference or orderReference is required by Peppol BIS 3.0 (BT-10).\",\n \"BR-10\"\n )\n );\n }\n\n // ── TaxCurrencyCode validation ──\n\n if (input.taxCurrency && input.taxCurrency !== (input.currency ?? \"EUR\") && !input.taxCurrencyRate) {\n errors.push(\n error(\n \"taxCurrencyRate\",\n \"Tax currency rate is required when taxCurrency differs from document currency\",\n \"BR-53\",\n \"Set taxCurrencyRate to the exchange rate from document currency to tax currency\"\n )\n );\n }\n\n if (input.taxCurrency && input.taxCurrency === (input.currency ?? \"EUR\")) {\n warnings.push(\n warning(\"taxCurrency\", \"Tax currency is the same as document currency — TaxCurrencyCode will be omitted\")\n );\n }\n\n if (input.taxCurrencyRate !== undefined && input.taxCurrencyRate <= 0) {\n errors.push(\n error(\n \"taxCurrencyRate\",\n `Tax currency rate must be positive, got ${input.taxCurrencyRate}`,\n undefined,\n \"Set to the exchange rate from document currency to tax currency\"\n )\n );\n }\n\n // ── Currency code validation (ISO 4217) ──\n\n if (input.currency && !getCurrency(input.currency)) {\n errors.push(\n error(\n \"currency\",\n `Invalid currency code: \"${input.currency}\"`,\n undefined,\n 'Use ISO 4217 (e.g., \"EUR\", \"USD\", \"GBP\", \"JPY\"). See https://getpeppr.dev/docs/types/#currency'\n )\n );\n }\n\n if (input.taxCurrency && !getCurrency(input.taxCurrency)) {\n errors.push(\n error(\n \"taxCurrency\",\n `Invalid tax currency code: \"${input.taxCurrency}\"`,\n undefined,\n 'Use ISO 4217 (e.g., \"EUR\", \"USD\")'\n )\n );\n }\n\n // ── Warnings (non-blocking) ──\n\n if (!input.dueDate) {\n warnings.push(warning(\"dueDate\", \"No due date specified. Recommended for payment terms.\", \"BR-09\"));\n }\n\n if (!input.to?.vatNumber) {\n warnings.push(warning(\"to.vatNumber\", \"Buyer VAT number not provided. May be required for B2B.\"));\n }\n\n if (input.paymentMeans === 30 && !input.paymentIban) {\n warnings.push(\n warning(\n \"paymentIban\",\n \"Payment means is credit transfer but no IBAN provided. Buyer won't know where to pay.\"\n )\n );\n }\n\n // ── Cross-field validation ──\n\n if (input.from?.peppolId && input.to?.peppolId && input.from.peppolId === input.to.peppolId) {\n errors.push(\n error(\n \"to.peppolId\",\n \"Buyer and seller cannot have the same Peppol ID\",\n undefined,\n \"Check that 'from' and 'to' are different parties\"\n )\n );\n }\n\n // ── Country-specific rules (advisory warnings) ──\n\n const countryResult = validateCountryRules(input);\n warnings.push(...countryResult.warnings);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","/** SDK version — keep in sync with package.json on each release. */\nexport const SDK_VERSION = \"1.5.2\";\n","/**\n * getpeppr SDK Client\n *\n * The main entry point. Designed to feel like Stripe's SDK:\n *\n * const peppol = new Peppol({ apiKey: \"sk_live_...\" });\n * const result = await peppol.invoices.send({ from, to, lines });\n *\n * All requests go through the getpeppr API gateway (api.getpeppr.dev),\n * which handles Peppol delivery, billing, and usage tracking.\n * Use `baseUrl` to point to a custom instance or localhost.\n */\n\nimport type {\n PeppolConfig,\n InvoiceInput,\n CreditNoteInput,\n SendResult,\n ValidationResult,\n WebhookEvent,\n RetryConfig,\n DocumentStatus,\n WaitForOptions,\n PaginatedResult,\n InvoiceSummary,\n ListInvoicesOptions,\n DirectoryEntry,\n DirectorySearchOptions,\n DirectorySearchResult,\n PeppolId,\n DocumentFormat,\n ServerValidationResult,\n EventEntry,\n ListEventsOptions,\n BatchSendOptions,\n BatchSendResult,\n InvoiceOperationOptions,\n RequestLogEntry,\n ResponseLogEntry,\n Contact,\n ContactInput,\n ListContactsOptions,\n BankAccount,\n BankAccountInput,\n ListBankAccountsOptions,\n ImportInvoiceOptions,\n TransportType,\n Transport,\n TransportInput,\n TransportUpdateInput,\n MarkAsState,\n MarkAsOptions,\n InvoiceUpdateInput,\n} from \"../types/invoice.js\";\nimport { buildInvoiceXml, buildCreditNoteXml } from \"./ubl-builder.js\";\nimport { validateInvoice } from \"./validator.js\";\nimport { SDK_VERSION } from \"../version.js\";\n\n// ─── Backend Adapter Interface ──────────────────────────────\n\n/**\n * Backend adapter interface for the SDK's transport layer.\n * The default implementation hits the getpeppr API gateway.\n */\nexport interface BackendAdapter {\n /** Provider name (for logging) */\n readonly name: string;\n /** Send an invoice as structured JSON (gateway handles UBL generation) */\n sendInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult>;\n /** Create a draft invoice without sending (POST /invoices, no send_after_import) */\n createInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult>;\n /** Send an existing draft invoice by ID (POST /invoices/send/{id}, returns 204) */\n sendInvoiceById(id: string): Promise<void>;\n /** @deprecated Credit notes now route through sendInvoice with isCreditNote: true */\n sendCreditNote(input: CreditNoteInput): Promise<SendResult>;\n /** Validate an invoice server-side (free, no metering) */\n validateDocument(input: InvoiceInput): Promise<{ valid: boolean; errors: string[] }>;\n /** List invoices with pagination and filtering */\n listInvoices(options?: ListInvoicesOptions): Promise<PaginatedResult<InvoiceSummary>>;\n /** Get document status by ID */\n getStatus(documentId: string): Promise<SendResult>;\n /** Look up a Peppol participant in the directory */\n lookupDirectory(scheme: string, id: string): Promise<DirectoryEntry>;\n /** Search the Peppol Directory for participants */\n searchDirectory?(params: Record<string, string>): Promise<DirectorySearchResult>;\n /** Export an invoice in a specific format (e.g., PDF) — returns raw binary */\n getInvoiceAs(id: string, format: DocumentFormat): Promise<ArrayBuffer>;\n /** Validate an invoice server-side through the getpeppr gateway's offline SDK-backed checks. */\n validateDocumentServer(input: InvoiceInput): Promise<ServerValidationResult>;\n /** List events with optional filtering and pagination */\n listEvents(options?: ListEventsOptions): Promise<PaginatedResult<EventEntry>>;\n /** Acknowledge a received invoice (POST /invoices/{id}/ack) */\n acknowledgeInvoice(id: string): Promise<SendResult>;\n /** List contacts with optional filtering and pagination */\n listContacts(options?: ListContactsOptions): Promise<PaginatedResult<Contact>>;\n /** Get a single contact by ID */\n getContact(id: string): Promise<Contact>;\n /** Create a new contact */\n createContact(input: ContactInput): Promise<Contact>;\n /** Update an existing contact */\n updateContact(id: string, input: Partial<ContactInput>): Promise<Contact>;\n /** Delete a contact */\n deleteContact(id: string): Promise<void>;\n /** List bank accounts with optional pagination */\n listBankAccounts(options?: ListBankAccountsOptions): Promise<PaginatedResult<BankAccount>>;\n /** Get a single bank account by ID */\n getBankAccount(id: string): Promise<BankAccount>;\n /** Create a new bank account */\n createBankAccount(input: BankAccountInput): Promise<BankAccount>;\n /** Update an existing bank account */\n updateBankAccount(id: string, input: Partial<BankAccountInput>): Promise<BankAccount>;\n /** Delete a bank account */\n deleteBankAccount(id: string): Promise<void>;\n /** Import an invoice from a file (XML, PDF, etc.) */\n importInvoice(options: ImportInvoiceOptions): Promise<SendResult>;\n /** List all available transport types (global, not account-scoped) */\n listTransportTypes(): Promise<TransportType[]>;\n /** List configured transports for this account */\n listTransports(): Promise<Transport[]>;\n /** Get a single transport by code */\n getTransport(code: string): Promise<Transport>;\n /** Create a new transport */\n createTransport(input: TransportInput): Promise<Transport>;\n /** Update an existing transport */\n updateTransport(code: string, input: TransportUpdateInput): Promise<Transport>;\n /** Delete a transport */\n deleteTransport(code: string): Promise<void>;\n /** Update an existing invoice */\n updateInvoice(id: string, input: InvoiceUpdateInput): Promise<SendResult>;\n /** Delete an invoice */\n deleteInvoice(id: string): Promise<SendResult>;\n /** Transition an invoice to a new state */\n markInvoiceAs(id: string, state: MarkAsState, options?: MarkAsOptions): Promise<SendResult>;\n}\n\n// ─── Retry & Header Utilities ────────────────────────────────────────\n\n/**\n * Case-insensitive header lookup. Per RFC 7230 §3.2, HTTP header names are\n * case-insensitive. Some adapters (axios default, Cloudflare Workers, proxies) lowercase\n * header keys, which made the strict bracket lookup miss user-supplied lowercase\n * keys and silently disabled retry safety on POST requests with idempotency keys.\n *\n * When multiple headers match (e.g. \"Idempotency-Key\" and \"idempotency-key\" both present),\n * returns the value of the first matching key in insertion order.\n *\n * @internal — exported for testing only; not part of the public SDK surface.\n */\nexport function findHeaderCaseInsensitive(\n headers: Record<string, string> | undefined,\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n const target = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === target) return value;\n }\n return undefined;\n}\n\nconst RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction calculateRetryDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n retryAfterMs?: number,\n): number {\n if (retryAfterMs !== undefined) return Math.min(retryAfterMs, maxDelayMs);\n const exponentialDelay = initialDelayMs * Math.pow(2, attempt);\n const jitter = Math.random() * initialDelayMs;\n return Math.min(exponentialDelay + jitter, maxDelayMs);\n}\n\n/**\n * Parse the Retry-After header value into milliseconds.\n * Supports integer seconds (e.g., \"1\", \"60\") and HTTP-date format.\n * Returns undefined if the header is missing or unparseable.\n */\nfunction parseRetryAfter(headerValue: string | null): number | undefined {\n if (!headerValue) return undefined;\n\n // Try integer seconds first (most common for rate limiters)\n const seconds = Number(headerValue);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n // Try HTTP-date format (e.g., \"Wed, 21 Oct 2025 07:28:00 GMT\")\n const dateMs = Date.parse(headerValue);\n if (!Number.isNaN(dateMs)) {\n const delayMs = dateMs - Date.now();\n return delayMs > 0 ? delayMs : 0;\n }\n\n return undefined;\n}\n\nfunction isRetryableError(error: unknown): boolean {\n if (error instanceof PeppolApiError) {\n return RETRYABLE_STATUS_CODES.has(error.statusCode);\n }\n // Retry on timeout/abort errors\n if (error instanceof Error && error.name === \"AbortError\") {\n return true;\n }\n // Retry on transient network errors (DNS failure, connection refused, reset, timeout, etc.)\n if (error instanceof TypeError && /fetch failed|network|ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT/i.test(error.message)) {\n return true;\n }\n return false;\n}\n\n// ─── getpeppr API Adapter ───────────────────────────────────\n\nconst DEFAULT_BASE_URL = \"https://api.getpeppr.dev/v1\";\n\nclass GetpepprAdapter implements BackendAdapter {\n readonly name = \"getpeppr\";\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private retryConfig: Required<RetryConfig>;\n private onRequest?: (entry: RequestLogEntry) => void;\n private onResponse?: (entry: ResponseLogEntry) => void;\n\n constructor(config: PeppolConfig) {\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 30_000;\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.retryConfig = {\n maxRetries: config.retry?.maxRetries ?? 3,\n initialDelayMs: config.retry?.initialDelayMs ?? 500,\n maxDelayMs: config.retry?.maxDelayMs ?? 30_000,\n };\n this.onRequest = config.onRequest;\n this.onResponse = config.onResponse;\n }\n\n private async request<T>(method: string, path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T> {\n const { maxRetries, initialDelayMs, maxDelayMs } = this.retryConfig;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await this.doRequest<T>(method, path, body, extraHeaders);\n } catch (err) {\n lastError = err;\n // 429 (rate limit) is always safe to retry — the request was never processed.\n // For other retryable errors (500, 502, 503, 504, network failures),\n // only retry non-idempotent methods (POST, PUT, PATCH) if an Idempotency-Key was\n // provided, to prevent duplicate side effects (e.g., sending the same invoice twice).\n const is429 = err instanceof PeppolApiError && err.statusCode === 429;\n const isSafeMethod = /^(GET|DELETE|HEAD)$/i.test(method);\n const hasIdempotencyKey = !!findHeaderCaseInsensitive(extraHeaders, \"Idempotency-Key\");\n const canRetry = is429 || isSafeMethod || hasIdempotencyKey;\n if (attempt < maxRetries && canRetry && isRetryableError(err)) {\n const retryAfterMs = err instanceof PeppolApiError ? err.retryAfterMs : undefined;\n await sleep(calculateRetryDelay(attempt, initialDelayMs, maxDelayMs, retryAfterMs));\n continue;\n }\n throw err;\n }\n }\n\n throw lastError;\n }\n\n private async doRequest<T>(method: string, path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const requestHeaders: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": `getpeppr-sdk/${SDK_VERSION}`,\n ...extraHeaders,\n };\n\n const startTime = Date.now();\n if (this.onRequest) {\n try {\n this.onRequest({\n method,\n url,\n headers: { ...requestHeaders },\n body,\n timestamp: startTime,\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers: requestHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"Unknown error\");\n const retryAfterMs = response.status === 429\n ? parseRetryAfter(response.headers.get(\"Retry-After\"))\n : undefined;\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: errorBody,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n throw new PeppolApiError(\n `getpeppr API error (${response.status}): ${errorBody}`,\n response.status,\n errorBody,\n retryAfterMs,\n );\n }\n\n // 204 No Content — no body to parse (e.g., sendInvoiceById)\n if (response.status === 204) {\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: undefined,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n return undefined as T;\n }\n\n let responseBody: T;\n try {\n responseBody = (await response.json()) as T;\n } catch {\n throw new PeppolApiError(\n `getpeppr API error: unexpected response format (status ${response.status})`,\n response.status,\n \"Response body is not valid JSON\",\n );\n }\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: responseBody,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n return responseBody;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n // NOTE: sendInvoice and createInvoice hit the same SDK endpoint (POST /invoices).\n // The gateway (Tasks 9-10) differentiates them: sendInvoice wraps with\n // { invoice: {...}, send_after_import: true }, createInvoice omits the flag.\n async sendInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n const headers: Record<string, string> = {};\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n }\n if (options?.validateRecipient) {\n headers[\"X-Validate-Recipient\"] = options.validateRecipient === true ? \"warn\" : String(options.validateRecipient);\n }\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/invoices\", input, headers);\n return parseSendResult(result);\n }\n\n async createInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n const headers: Record<string, string> = {};\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n }\n if (options?.validateRecipient) {\n headers[\"X-Validate-Recipient\"] = options.validateRecipient === true ? \"warn\" : String(options.validateRecipient);\n }\n // Signal to the gateway that this is a draft (no auto-send).\n // The gateway reads `_draft` and strips it before forwarding to B2BRouter.\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/invoices\", { ...input, _draft: true }, headers);\n return parseSendResult(result);\n }\n\n async sendInvoiceById(id: string): Promise<void> {\n await this.request<void>(\"POST\", `/invoices/send/${id}`);\n }\n\n async sendCreditNote(input: CreditNoteInput): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/credit-notes\", input);\n return parseSendResult(result);\n }\n\n async validateDocument(input: InvoiceInput): Promise<{ valid: boolean; errors: string[] }> {\n return this.request<{ valid: boolean; errors: string[] }>(\"POST\", \"/validate\", input);\n }\n\n async listInvoices(options?: ListInvoicesOptions): Promise<PaginatedResult<InvoiceSummary>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n if (options?.includeLines) params.set(\"include\", \"lines\");\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/invoices${query}`);\n\n // Gateway returns { invoices: [...], meta: {...} }\n const invoices = (result.invoices ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: invoices.map((inv) => ({\n id: String(inv.id ?? \"\"),\n number: String(inv.number ?? \"\"),\n status: mapStatus(String(inv.state ?? inv.status ?? \"submitted\")),\n createdAt: inv.created_at ? String(inv.created_at) : undefined,\n })),\n meta: {\n totalCount: Number(meta?.total_count ?? invoices.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta ? Number(meta.total_count) > Number(meta.offset) + Number(meta.limit) : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async getStatus(documentId: string): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/invoices/${documentId}`);\n return parseSendResult(result);\n }\n\n async lookupDirectory(scheme: string, id: string): Promise<DirectoryEntry> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/directory/${scheme}/${id}`);\n return parseDirectoryEntry(result);\n }\n\n async searchDirectory(params: Record<string, string>): Promise<DirectorySearchResult> {\n const query = new URLSearchParams(params).toString();\n return this.request<DirectorySearchResult>(\"GET\", `/directory/search?${query}`);\n }\n\n async getInvoiceAs(id: string, format: DocumentFormat): Promise<ArrayBuffer> {\n const { maxRetries, initialDelayMs, maxDelayMs } = this.retryConfig;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await this.doRequestBinary(`/invoices/${id}/as/${format}`);\n } catch (err) {\n lastError = err;\n if (attempt < maxRetries && isRetryableError(err)) {\n const retryAfterMs = err instanceof PeppolApiError ? err.retryAfterMs : undefined;\n await sleep(calculateRetryDelay(attempt, initialDelayMs, maxDelayMs, retryAfterMs));\n continue;\n }\n throw err;\n }\n }\n\n throw lastError;\n }\n\n private async doRequestBinary(path: string): Promise<ArrayBuffer> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const requestHeaders = {\n Authorization: `Bearer ${this.apiKey}`,\n };\n\n const startTime = Date.now();\n if (this.onRequest) {\n try {\n this.onRequest({\n method: \"GET\",\n url,\n headers: { ...requestHeaders },\n timestamp: startTime,\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: requestHeaders,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"Unknown error\");\n const retryAfterMs = response.status === 429\n ? parseRetryAfter(response.headers.get(\"Retry-After\"))\n : undefined;\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: errorBody,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n throw new PeppolApiError(\n `getpeppr API error (${response.status}): ${errorBody}`,\n response.status,\n errorBody,\n retryAfterMs,\n );\n }\n\n const responseBody = await response.arrayBuffer();\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: `[ArrayBuffer: ${responseBody.byteLength} bytes]`,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n return responseBody;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async validateDocumentServer(input: InvoiceInput): Promise<ServerValidationResult> {\n return this.request<ServerValidationResult>(\"POST\", \"/validate/server\", input);\n }\n\n async listEvents(options?: ListEventsOptions): Promise<PaginatedResult<EventEntry>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n if (options?.invoiceId) params.set(\"invoiceId\", options.invoiceId);\n if (options?.dateFrom) params.set(\"dateFrom\", options.dateFrom);\n if (options?.dateTo) params.set(\"dateTo\", options.dateTo);\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/events${query}`);\n\n const events = (result.events ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: events.map((evt) => ({\n name: String(evt.name ?? \"\"),\n text: String(evt.text ?? \"\"),\n notes: evt.notes ? String(evt.notes) : undefined,\n createdAt: String(evt.createdAt ?? evt.created_at ?? new Date().toISOString()),\n invoice: evt.invoice as EventEntry[\"invoice\"],\n contact: evt.contact as EventEntry[\"contact\"],\n })),\n meta: {\n totalCount: Number(meta?.total_count ?? meta?.totalCount ?? events.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta\n ? Number(meta.total_count ?? meta.totalCount) > Number(meta.offset) + Number(meta.limit)\n : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async acknowledgeInvoice(id: string): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"POST\", `/invoices/${id}/ack`);\n return parseSendResult(result);\n }\n\n async updateInvoice(id: string, input: InvoiceUpdateInput): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/invoices/${id}`, input);\n return parseSendResult(result);\n }\n\n async deleteInvoice(id: string): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"DELETE\", `/invoices/${id}`);\n return parseSendResult(result);\n }\n\n async markInvoiceAs(id: string, state: MarkAsState, options?: MarkAsOptions): Promise<SendResult> {\n const body: Record<string, unknown> = { state };\n if (options?.commit) body.commit = options.commit;\n if (options?.reason) body.reason = options.reason;\n const result = await this.request<Record<string, unknown>>(\"POST\", `/invoices/${id}/mark-as`, body);\n return parseSendResult(result);\n }\n\n async listContacts(options?: ListContactsOptions): Promise<PaginatedResult<Contact>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n if (options?.name) params.set(\"name\", options.name);\n if (options?.isClient != null) params.set(\"isClient\", String(options.isClient));\n if (options?.isProvider != null) params.set(\"isProvider\", String(options.isProvider));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/contacts${query}`);\n\n const contacts = (result.contacts ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: contacts.map(parseContact),\n meta: {\n totalCount: Number(meta?.total_count ?? meta?.totalCount ?? contacts.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta\n ? Number(meta.total_count ?? meta.totalCount) > Number(meta.offset) + Number(meta.limit)\n : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async getContact(id: string): Promise<Contact> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/contacts/${id}`);\n return parseContact(result);\n }\n\n async createContact(input: ContactInput): Promise<Contact> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/contacts\", input);\n return parseContact(result);\n }\n\n async updateContact(id: string, input: Partial<ContactInput>): Promise<Contact> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/contacts/${id}`, input);\n return parseContact(result);\n }\n\n async deleteContact(id: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/contacts/${id}`);\n }\n\n async listBankAccounts(options?: ListBankAccountsOptions): Promise<PaginatedResult<BankAccount>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/bank-accounts${query}`);\n\n const bankAccounts = (result.bankAccounts ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: bankAccounts.map(parseBankAccount),\n meta: {\n totalCount: Number(meta?.total_count ?? meta?.totalCount ?? bankAccounts.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta\n ? Number(meta.total_count ?? meta.totalCount) > Number(meta.offset) + Number(meta.limit)\n : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async getBankAccount(id: string): Promise<BankAccount> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/bank-accounts/${id}`);\n return parseBankAccount(result);\n }\n\n async createBankAccount(input: BankAccountInput): Promise<BankAccount> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/bank-accounts\", input);\n return parseBankAccount(result);\n }\n\n async updateBankAccount(id: string, input: Partial<BankAccountInput>): Promise<BankAccount> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/bank-accounts/${id}`, input);\n return parseBankAccount(result);\n }\n\n async deleteBankAccount(id: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/bank-accounts/${id}`);\n }\n\n async importInvoice(options: ImportInvoiceOptions): Promise<SendResult> {\n const body = {\n file: arrayBufferToBase64(options.file),\n filename: options.filename,\n mimeType: options.mimeType ?? detectMimeType(options.filename),\n };\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/invoices/import\", body);\n return parseSendResult(result);\n }\n\n async listTransportTypes(): Promise<TransportType[]> {\n const result = await this.request<Record<string, unknown>>(\"GET\", \"/transports/types\");\n const types = (result.transportTypes ?? result.data ?? []) as Record<string, unknown>[];\n return types.map((t) => ({\n code: String(t.code ?? \"\"),\n name: String(t.name ?? \"\"),\n }));\n }\n\n async listTransports(): Promise<Transport[]> {\n const result = await this.request<Record<string, unknown>>(\"GET\", \"/transports\");\n const transports = (result.transports ?? result.data ?? []) as Record<string, unknown>[];\n return transports.map(parseTransport);\n }\n\n async getTransport(code: string): Promise<Transport> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/transports/${code}`);\n return parseTransport(result);\n }\n\n async createTransport(input: TransportInput): Promise<Transport> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/transports\", input);\n return parseTransport(result);\n }\n\n async updateTransport(code: string, input: TransportUpdateInput): Promise<Transport> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/transports/${code}`, input);\n return parseTransport(result);\n }\n\n async deleteTransport(code: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/transports/${code}`);\n }\n}\n\n// ─── Import Helpers ──────────────────────────────────────────\n\n/** Convert ArrayBuffer or Uint8Array to base64 string (works in all runtimes). */\nexport function arrayBufferToBase64(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/** Detect MIME type from a filename's extension. */\nexport function detectMimeType(filename: string): string {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n switch (ext) {\n case \"xml\": return \"application/xml\";\n case \"pdf\": return \"application/pdf\";\n case \"json\": return \"application/json\";\n default: return \"application/octet-stream\";\n }\n}\n\nfunction parseSendResult(result: Record<string, unknown>): SendResult {\n return {\n id: String(result.id ?? \"\"),\n status: mapStatus(String(result.status ?? \"submitted\")),\n peppolMessageId: (result.peppolMessageId ?? result.peppol_message_id) as string | undefined,\n createdAt: String(result.createdAt ?? result.updatedAt ?? result.created_at ?? new Date().toISOString()),\n ublXml: result.ublXml as string | undefined,\n warnings: Array.isArray(result.warnings) ? result.warnings : undefined,\n };\n}\n\nfunction parseDirectoryEntry(result: Record<string, unknown>): DirectoryEntry {\n const participant = isRecord(result.participant) ? result.participant : result;\n const scheme = participant.scheme == null ? undefined : String(participant.scheme);\n const id = participant.id == null ? undefined : String(participant.id);\n const peppolId =\n participant.peppolId == null\n ? formatPeppolId(scheme, id)\n : String(participant.peppolId);\n\n return {\n name: String(participant.name ?? \"\"),\n peppolId: peppolId as PeppolId,\n country: String(participant.country ?? \"\"),\n capabilities: Array.isArray(participant.capabilities)\n ? participant.capabilities.map(String)\n : [],\n registrationDate: participant.registrationDate == null ? undefined : String(participant.registrationDate),\n vatNumber: participant.vatNumber == null ? undefined : String(participant.vatNumber),\n additionalIds: Array.isArray(participant.additionalIds)\n ? participant.additionalIds.filter(isRecord).map((entry) => ({\n scheme: String(entry.scheme ?? \"\"),\n value: String(entry.value ?? \"\"),\n }))\n : undefined,\n contactInfo: isRecord(participant.contactInfo)\n ? {\n name: participant.contactInfo.name == null ? undefined : String(participant.contactInfo.name),\n email: participant.contactInfo.email == null ? undefined : String(participant.contactInfo.email),\n phone: participant.contactInfo.phone == null ? undefined : String(participant.contactInfo.phone),\n }\n : undefined,\n website: participant.website == null ? undefined : String(participant.website),\n };\n}\n\nfunction formatPeppolId(scheme: string | undefined, id: string | undefined): string {\n if (!id) return scheme ? `${scheme}:` : \"\";\n if (id.includes(\":\")) return id;\n return scheme ? `${scheme}:${id}` : id;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseContact(raw: Record<string, unknown>): Contact {\n const contact: Contact = {\n id: String(raw.id ?? \"\"),\n name: String(raw.name ?? \"\"),\n };\n\n if (raw.peppolId != null) contact.peppolId = String(raw.peppolId);\n if (raw.vatNumber != null) contact.vatNumber = String(raw.vatNumber);\n if (raw.companyId != null) contact.companyId = String(raw.companyId);\n if (raw.street != null) contact.street = String(raw.street);\n if (raw.city != null) contact.city = String(raw.city);\n if (raw.postalCode != null) contact.postalCode = String(raw.postalCode);\n if (raw.country != null) contact.country = String(raw.country);\n if (raw.email != null) contact.email = String(raw.email);\n if (raw.phone != null) contact.phone = String(raw.phone);\n if (raw.isClient != null) contact.isClient = Boolean(raw.isClient);\n if (raw.isProvider != null) contact.isProvider = Boolean(raw.isProvider);\n if (raw.createdAt != null) contact.createdAt = String(raw.createdAt);\n if (raw.updatedAt != null) contact.updatedAt = String(raw.updatedAt);\n if (raw.directoryVerified != null) contact.directoryVerified = Boolean(raw.directoryVerified);\n if (raw.directoryLastChecked != null) contact.directoryLastChecked = String(raw.directoryLastChecked);\n\n return contact;\n}\n\nfunction parseBankAccount(raw: Record<string, unknown>): BankAccount {\n const account: BankAccount = {\n id: String(raw.id ?? \"\"),\n name: String(raw.name ?? \"\"),\n type: (raw.type === \"number\" ? \"number\" : \"iban\") as \"iban\" | \"number\",\n };\n\n if (raw.iban != null) account.iban = String(raw.iban);\n if (raw.number != null) account.number = String(raw.number);\n if (raw.bic != null) account.bic = String(raw.bic);\n if (raw.country != null) account.country = String(raw.country);\n if (raw.createdAt != null) account.createdAt = String(raw.createdAt);\n if (raw.updatedAt != null) account.updatedAt = String(raw.updatedAt);\n\n return account;\n}\n\nfunction parseTransport(raw: Record<string, unknown>): Transport {\n return {\n id: String(raw.id ?? \"\"),\n transportTypeCode: String(raw.transportTypeCode ?? \"\"),\n name: String(raw.name ?? \"\"),\n status: raw.status ? String(raw.status) : undefined,\n };\n}\n\n// getpeppr gateway document lifecycle states.\n// Mapped from Storecove webhook events. See: Storecove API v2 §3.3.4\nconst VALID_STATUSES = new Set<DocumentStatus>([\n \"submitted\", \"delivered\", \"accepted\", \"rejected\", \"paid\", \"failed\",\n \"cleared\", \"acknowledged\", \"in_process\", \"under_query\",\n \"conditionally_accepted\", \"partially_paid\", \"no_action\",\n \"unknown\", // explicitly known: gateway may emit this when it can't map a Storecove status\n]);\n\n// Note: each call to mapStatus that hits the unknown fallback emits its own console.warn.\n// No dedup is intentional — callers see the warning proportionally to how often the\n// unknown status appears (matches Stripe/AWS SDK convention).\n/** @internal — exported for testing only; not part of the public SDK surface. */\nexport function mapStatus(raw: string): DocumentStatus {\n const s = raw.toLowerCase() as DocumentStatus;\n if (VALID_STATUSES.has(s)) return s;\n console.warn(\n `[getpeppr] Unknown gateway status received: \"${raw}\" — ` +\n `please report to support@getpeppr.dev. Coercing to \"unknown\".`,\n );\n return \"unknown\";\n}\n\n// ─── Error Classes ──────────────────────────────────────────\n\nexport class PeppolError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PeppolError\";\n }\n}\n\nexport class PeppolValidationError extends PeppolError {\n constructor(\n message: string,\n public readonly validation: ValidationResult\n ) {\n super(message);\n this.name = \"PeppolValidationError\";\n }\n}\n\nexport class PeppolApiError extends PeppolError {\n /** Parsed Retry-After delay in milliseconds (present on 429 responses) */\n public readonly retryAfterMs?: number;\n\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly responseBody: string,\n retryAfterMs?: number,\n ) {\n super(message);\n this.name = \"PeppolApiError\";\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n// ─── Main SDK Client ────────────────────────────────────────\n\nexport class Peppol {\n private adapter: BackendAdapter;\n public readonly invoices: InvoiceOperations;\n public readonly creditNotes: CreditNoteOperations;\n public readonly directory: DirectoryOperations;\n public readonly events: EventOperations;\n public readonly contacts: ContactOperations;\n public readonly bankAccounts: BankAccountOperations;\n public readonly transports: TransportOperations;\n\n constructor(config: PeppolConfig) {\n if (!config.apiKey) {\n throw new PeppolError(\n 'API key is required. Sign up at https://console.getpeppr.dev to get your sandbox key.'\n );\n }\n\n this.adapter = new GetpepprAdapter(config);\n this.invoices = new InvoiceOperations(this.adapter);\n this.creditNotes = new CreditNoteOperations(this.adapter);\n this.directory = new DirectoryOperations(this.adapter);\n this.events = new EventOperations(this.adapter);\n this.contacts = new ContactOperations(this.adapter);\n this.bankAccounts = new BankAccountOperations(this.adapter);\n this.transports = new TransportOperations(this.adapter);\n }\n\n /**\n * Validate an invoice without sending it.\n * Useful for pre-flight checks in your UI.\n */\n validate(input: InvoiceInput): ValidationResult {\n return validateInvoice(input);\n }\n\n /**\n * Generate UBL XML without sending.\n * Useful for debugging or manual submission.\n */\n toXml(input: InvoiceInput): string {\n const validation = validateInvoice(input);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Invoice validation failed: ${validation.errors.map((e) => e.message).join(\"; \")}`,\n validation\n );\n }\n if (input.isCreditNote) {\n return buildCreditNoteXml(input as unknown as CreditNoteInput);\n }\n return buildInvoiceXml(input);\n }\n}\n\n/** @internal — exported for testing only; not part of the public SDK surface. */\nexport async function* paginate<T>(\n fetchPage: (offset: number, limit: number) => Promise<PaginatedResult<T>>,\n options?: { limit?: number },\n): AsyncGenerator<T> {\n const pageSize = options?.limit ?? 25;\n let offset = 0;\n\n while (true) {\n const page = await fetchPage(offset, pageSize);\n if (page.data.length === 0) break; // safety: empty page (even with hasMore=true) ends iteration\n for (const item of page.data) {\n yield item;\n }\n if (!page.meta.hasMore) break;\n offset += page.data.length; // FIX (GPR-414 #6): was += pageSize, which silently skipped records on partial pages\n }\n}\n\nclass InvoiceOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Create a draft invoice without sending it.\n * Validates input client-side, then creates the invoice on B2BRouter.\n * Use `sendById()` to send the draft when ready.\n *\n * @example\n * ```ts\n * const draft = await peppol.invoices.create({ number: \"INV-001\", to, lines });\n * // Later, when ready:\n * await peppol.invoices.sendById(draft.id);\n * ```\n */\n async create(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n const validation = validateInvoice(input);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Invoice validation failed:\\n${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (${e.suggestion})` : \"\"}`).join(\"\\n\")}`,\n validation\n );\n }\n\n const result = await this.adapter.createInvoice(input, options);\n\n if (validation.warnings.length > 0) {\n result.warnings = validation.warnings;\n }\n\n return result;\n }\n\n /**\n * Send an existing draft invoice by ID.\n * The invoice must have been previously created with `create()`.\n *\n * @example\n * ```ts\n * await peppol.invoices.sendById(\"inv-1\");\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support draft sending\n */\n async sendById(id: string): Promise<void> {\n return this.adapter.sendInvoiceById(id);\n }\n\n /**\n * Send an invoice via Peppol.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.send({\n * number: \"INV-001\",\n * from: { name: \"My Company\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * to: { name: \"Client Co\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * lines: [\n * { description: \"Consulting\", quantity: 10, unitPrice: 150, vatRate: 21 }\n * ]\n * });\n * ```\n */\n async send(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n // Client-side validation for fast feedback\n const validation = validateInvoice(input);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Invoice validation failed:\\n${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (${e.suggestion})` : \"\"}`).join(\"\\n\")}`,\n validation\n );\n }\n\n // Send structured JSON — gateway handles UBL generation\n const result = await this.adapter.sendInvoice(input, options);\n\n if (validation.warnings.length > 0) {\n result.warnings = validation.warnings;\n }\n\n return result;\n }\n\n /** List invoices with pagination, filtering, and proper metadata */\n async list(options?: ListInvoicesOptions): Promise<PaginatedResult<InvoiceSummary>> {\n return this.adapter.listInvoices(options);\n }\n\n /**\n * Async iterator over all invoices, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const invoice of peppol.invoices.listAll()) {\n * console.log(invoice.id, invoice.status);\n * }\n * ```\n */\n listAll(options?: Omit<ListInvoicesOptions, \"offset\">): AsyncIterable<InvoiceSummary> {\n return paginate(\n (offset, limit) => this.adapter.listInvoices({ ...options, offset, limit }),\n options,\n );\n }\n\n /** Get the status of a sent invoice */\n async getStatus(documentId: string): Promise<SendResult> {\n return this.adapter.getStatus(documentId);\n }\n\n /**\n * Export an invoice in a specific format (e.g., PDF, UBL XML).\n * Returns raw binary data as an ArrayBuffer.\n *\n * @example\n * ```ts\n * const pdf = await peppol.invoices.getAs(\"inv-123\", \"pdf\");\n * fs.writeFileSync(\"invoice.pdf\", Buffer.from(pdf));\n * ```\n */\n async getAs(id: string, format: DocumentFormat): Promise<ArrayBuffer> {\n return this.adapter.getInvoiceAs(id, format);\n }\n\n /**\n * Validate an invoice server-side using the getpeppr gateway's offline SDK-backed checks.\n * The gateway runs SDK validation, verifies UBL XML generation, and evaluates offline\n * Peppol business rules without sending the invoice to Storecove.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.validateServer({\n * number: \"INV-001\",\n * to: { name: \"Acme\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * lines: [{ description: \"Item\", quantity: 1, unitPrice: 100, vatRate: 21 }]\n * });\n * console.log(result.valid, result.schematron.errors);\n * ```\n * Validation findings return a structured result with valid=false. Transport, auth,\n * malformed request, and unexpected gateway failures still throw PeppolApiError.\n */\n async validateServer(input: InvoiceInput): Promise<ServerValidationResult> {\n return this.adapter.validateDocumentServer(input);\n }\n\n /**\n * Import an invoice from a file (XML, PDF, JSON).\n * The file is base64-encoded and sent to the gateway, which forwards it\n * as multipart/form-data to B2BRouter's import endpoint.\n *\n * @example\n * ```ts\n * const xmlBytes = fs.readFileSync(\"invoice.xml\");\n * const result = await peppol.invoices.importFile({\n * file: xmlBytes,\n * filename: \"invoice.xml\",\n * });\n * console.log(result.id, result.status);\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support file import\n */\n async importFile(options: ImportInvoiceOptions): Promise<SendResult> {\n return this.adapter.importInvoice(options);\n }\n\n /**\n * Acknowledge a received invoice.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.acknowledge(\"inv-123\");\n * console.log(result.status); // \"accepted\"\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support acknowledgement\n */\n async acknowledge(id: string): Promise<SendResult> {\n return this.adapter.acknowledgeInvoice(id);\n }\n\n /**\n * Update an existing invoice (draft only).\n * Only include the fields you want to change — partial updates are supported.\n *\n * @example\n * ```ts\n * const updated = await peppol.invoices.update(\"inv-123\", {\n * dueDate: \"2026-04-01\",\n * lines: [\n * { id: \"line-1\", quantity: 5 },\n * { id: \"line-2\", _destroy: true },\n * ],\n * });\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support invoice updates\n */\n async update(id: string, input: InvoiceUpdateInput): Promise<SendResult> {\n return this.adapter.updateInvoice(id, input);\n }\n\n /**\n * Delete an invoice.\n *\n * @example\n * ```ts\n * const deleted = await peppol.invoices.delete(\"inv-123\");\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support invoice deletion\n */\n async delete(id: string): Promise<SendResult> {\n return this.adapter.deleteInvoice(id);\n }\n\n /**\n * Transition an invoice to a new state.\n * B2BRouter validates the state machine — invalid transitions return an error.\n *\n * @example\n * ```ts\n * await peppol.invoices.markAs(\"inv-123\", \"accepted\");\n * await peppol.invoices.markAs(\"inv-123\", \"paid\", {\n * commit: \"with_mail\",\n * reason: \"Payment received\",\n * });\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support state transitions\n */\n async markAs(id: string, state: MarkAsState, options?: MarkAsOptions): Promise<SendResult> {\n return this.adapter.markInvoiceAs(id, state, options);\n }\n\n /**\n * Send multiple invoices in parallel with controlled concurrency.\n * Each invoice is validated and sent individually — failures don't affect other invoices\n * unless `stopOnError: true` is set.\n *\n * The SDK's built-in retry logic (including 429 Retry-After) provides automatic\n * rate-limit handling at the request level.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.sendBatch([invoice1, invoice2, invoice3], {\n * concurrency: 3,\n * });\n * console.log(`${result.succeeded.length} sent, ${result.failed.length} failed`);\n * ```\n */\n async sendBatch(\n inputs: InvoiceInput[],\n options?: BatchSendOptions,\n ): Promise<BatchSendResult> {\n const concurrency = options?.concurrency ?? 5;\n const stopOnError = options?.stopOnError ?? false;\n\n const succeeded: BatchSendResult[\"succeeded\"] = [];\n const failed: BatchSendResult[\"failed\"] = [];\n let stopped = false;\n\n // Process in chunks of `concurrency` size\n for (let i = 0; i < inputs.length; i += concurrency) {\n if (stopped) break;\n\n const chunk = inputs.slice(i, i + concurrency);\n const promises = chunk.map(async (input, j) => {\n const index = i + j;\n if (stopped) return;\n try {\n const result = await this.send(input);\n succeeded.push({ index, result });\n } catch (error) {\n failed.push({ index, input, error: error as Error });\n if (stopOnError) {\n stopped = true;\n }\n }\n });\n\n await Promise.all(promises);\n }\n\n return { succeeded, failed, total: inputs.length };\n }\n\n /**\n * Poll until an invoice reaches a target status.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.waitFor(id, \"accepted\", { timeout: 60000 });\n * ```\n */\n async waitFor(\n documentId: string,\n targetStatus: DocumentStatus | DocumentStatus[],\n options?: WaitForOptions,\n ): Promise<SendResult> {\n const timeout = options?.timeout ?? 120_000;\n const interval = options?.interval ?? 5_000;\n const targets = Array.isArray(targetStatus) ? targetStatus : [targetStatus];\n const terminalFailures: DocumentStatus[] = [\"failed\", \"rejected\"];\n const startTime = Date.now();\n\n while (true) {\n const result = await this.getStatus(documentId);\n\n if (targets.includes(result.status)) {\n return result;\n }\n\n if (terminalFailures.includes(result.status)) {\n throw new PeppolError(\n `Document ${documentId} reached terminal status \"${result.status}\" while waiting for \"${targets.join('\" or \"')}\"`\n );\n }\n\n if (Date.now() - startTime >= timeout) {\n throw new PeppolError(\n `Timed out waiting for document ${documentId} to reach status \"${targets.join('\" or \"')}\" (last: \"${result.status}\")`\n );\n }\n\n await sleep(interval);\n }\n }\n}\n\n/** @deprecated Use peppol.invoices.send() with isCreditNote: true instead */\nclass CreditNoteOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Send a credit note via Peppol.\n * @deprecated Use peppol.invoices.send({ ...input, isCreditNote: true }) instead.\n */\n async send(input: CreditNoteInput): Promise<SendResult> {\n // Convert to InvoiceInput with isCreditNote flag and delegate to sendInvoice\n const invoiceInput: InvoiceInput = {\n ...input,\n isCreditNote: true,\n invoiceReference: input.invoiceReference,\n };\n\n const validation = validateInvoice(invoiceInput);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Credit note validation failed:\\n${validation.errors.map((e) => ` - ${e.field}: ${e.message}`).join(\"\\n\")}`,\n validation\n );\n }\n\n // Route through sendInvoice — B2BRouter has no separate credit-notes endpoint\n return this.adapter.sendInvoice(invoiceInput);\n }\n}\n\n// ─── Directory Operations ───────────────────────────────────\n\nclass DirectoryOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Look up a Peppol participant in the directory.\n *\n * @example\n * ```ts\n * const entry = await peppol.directory.lookup(\"0208:0685660237\");\n * console.log(entry.name, entry.capabilities);\n * ```\n */\n async lookup(peppolId: PeppolId): Promise<DirectoryEntry> {\n const colonIndex = peppolId.indexOf(\":\");\n if (colonIndex === -1) {\n throw new PeppolError(\n 'Invalid Peppol ID format. Expected \"scheme:id\" (e.g., \"0208:0685660237\")',\n );\n }\n const scheme = peppolId.slice(0, colonIndex);\n const id = peppolId.slice(colonIndex + 1);\n return this.adapter.lookupDirectory(scheme, id);\n }\n\n /**\n * Search the Peppol Directory for participants.\n *\n * @example\n * ```ts\n * const result = await peppol.directory.search({ name: \"Acme\", country: \"BE\" });\n * console.log(result.data); // DirectoryEntry[]\n * console.log(result.meta.totalCount);\n * ```\n */\n async search(options: DirectorySearchOptions): Promise<DirectorySearchResult> {\n if (!options.name && !options.country && !options.vatNumber) {\n throw new PeppolError(\"At least one search criterion is required (name, country, or vatNumber)\");\n }\n if (options.name && options.name.length < 3) {\n throw new PeppolError(\"Search name must be at least 3 characters\");\n }\n if (!this.adapter.searchDirectory) {\n throw new PeppolError(\"Directory search is not supported by this backend adapter\");\n }\n\n const params: Record<string, string> = {};\n if (options.name) params.name = options.name;\n if (options.country) params.country = options.country;\n if (options.vatNumber) params.vatNumber = options.vatNumber;\n if (options.limit !== undefined) params.limit = String(options.limit);\n if (options.offset !== undefined) params.offset = String(options.offset);\n\n return this.adapter.searchDirectory(params);\n }\n\n /**\n * Search the Peppol Directory by VAT number.\n * Convenience method — equivalent to `search({ vatNumber })`.\n *\n * @example\n * ```ts\n * const result = await peppol.directory.searchByVat(\"BE0685660237\");\n * ```\n */\n async searchByVat(vatNumber: string): Promise<DirectorySearchResult> {\n return this.search({ vatNumber });\n }\n}\n\n// ─── Event Operations ────────────────────────────────────────\n\nclass EventOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List events with optional filtering and pagination.\n *\n * @example\n * ```ts\n * const result = await peppol.events.list({ limit: 10 });\n * console.log(result.data, result.meta);\n *\n * // Filter by invoice\n * const invoiceEvents = await peppol.events.list({ invoiceId: \"inv-123\" });\n * ```\n */\n async list(options?: ListEventsOptions): Promise<PaginatedResult<EventEntry>> {\n return this.adapter.listEvents(options);\n }\n\n /**\n * Async iterator over all events, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const event of peppol.events.listAll({ invoiceId: \"inv-123\" })) {\n * console.log(event.name, event.createdAt);\n * }\n * ```\n */\n listAll(options?: Omit<ListEventsOptions, \"offset\">): AsyncIterable<EventEntry> {\n return paginate(\n (offset, limit) => this.adapter.listEvents({ ...options, offset, limit }),\n options,\n );\n }\n}\n\n// ─── Contact Operations ─────────────────────────────────────\n\nclass ContactOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List contacts with optional filtering and pagination.\n *\n * @example\n * ```ts\n * const result = await peppol.contacts.list({ limit: 10, isClient: true });\n * console.log(result.data, result.meta);\n * ```\n */\n async list(options?: ListContactsOptions): Promise<PaginatedResult<Contact>> {\n return this.adapter.listContacts(options);\n }\n\n /**\n * Get a single contact by ID.\n *\n * @example\n * ```ts\n * const contact = await peppol.contacts.get(\"123\");\n * console.log(contact.name, contact.peppolId);\n * ```\n */\n async get(id: string): Promise<Contact> {\n return this.adapter.getContact(id);\n }\n\n /**\n * Create a new contact.\n *\n * @example\n * ```ts\n * const contact = await peppol.contacts.create({\n * name: \"ACMEDIA\",\n * peppolId: \"0208:0685660237\",\n * country: \"BE\",\n * isClient: true,\n * });\n * ```\n */\n async create(input: ContactInput): Promise<Contact> {\n return this.adapter.createContact(input);\n }\n\n /**\n * Update an existing contact.\n *\n * @example\n * ```ts\n * const updated = await peppol.contacts.update(\"123\", { email: \"new@acme.com\" });\n * ```\n */\n async update(id: string, input: Partial<ContactInput>): Promise<Contact> {\n return this.adapter.updateContact(id, input);\n }\n\n /**\n * Delete a contact.\n *\n * @example\n * ```ts\n * await peppol.contacts.delete(\"123\");\n * ```\n */\n async delete(id: string): Promise<void> {\n return this.adapter.deleteContact(id);\n }\n\n /**\n * Async iterator over all contacts, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const contact of peppol.contacts.listAll({ isClient: true })) {\n * console.log(contact.name, contact.peppolId);\n * }\n * ```\n */\n listAll(options?: Omit<ListContactsOptions, \"offset\">): AsyncIterable<Contact> {\n return paginate(\n (offset, limit) => this.adapter.listContacts({ ...options, offset, limit }),\n options,\n );\n }\n}\n\n// ─── Bank Account Operations ─────────────────────────────────\n\nclass BankAccountOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List bank accounts with optional pagination.\n *\n * @example\n * ```ts\n * const result = await peppol.bankAccounts.list({ limit: 10 });\n * console.log(result.data, result.meta);\n * ```\n */\n async list(options?: ListBankAccountsOptions): Promise<PaginatedResult<BankAccount>> {\n return this.adapter.listBankAccounts(options);\n }\n\n /**\n * Get a single bank account by ID.\n *\n * @example\n * ```ts\n * const account = await peppol.bankAccounts.get(\"123\");\n * console.log(account.name, account.iban);\n * ```\n */\n async get(id: string): Promise<BankAccount> {\n return this.adapter.getBankAccount(id);\n }\n\n /**\n * Create a new bank account.\n *\n * @example\n * ```ts\n * const account = await peppol.bankAccounts.create({\n * name: \"Main Account\",\n * iban: \"BE68539007547034\",\n * bic: \"BBRUBEBB\",\n * country: \"BE\",\n * });\n * ```\n */\n async create(input: BankAccountInput): Promise<BankAccount> {\n return this.adapter.createBankAccount(input);\n }\n\n /**\n * Update an existing bank account.\n *\n * @example\n * ```ts\n * const updated = await peppol.bankAccounts.update(\"123\", { name: \"Updated Name\" });\n * ```\n */\n async update(id: string, input: Partial<BankAccountInput>): Promise<BankAccount> {\n return this.adapter.updateBankAccount(id, input);\n }\n\n /**\n * Delete a bank account.\n *\n * @example\n * ```ts\n * await peppol.bankAccounts.delete(\"123\");\n * ```\n */\n async delete(id: string): Promise<void> {\n return this.adapter.deleteBankAccount(id);\n }\n\n /**\n * Async iterator over all bank accounts, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const account of peppol.bankAccounts.listAll()) {\n * console.log(account.name, account.iban);\n * }\n * ```\n */\n listAll(options?: Omit<ListBankAccountsOptions, \"offset\">): AsyncIterable<BankAccount> {\n return paginate(\n (offset, limit) => this.adapter.listBankAccounts({ ...options, offset, limit }),\n options,\n );\n }\n}\n\n// ─── Transport Operations ────────────────────────────────────\n\nclass TransportOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List all available transport types in the network.\n * Returns global transport types (not account-scoped).\n *\n * @example\n * ```ts\n * const types = await peppol.transports.listTypes();\n * console.log(types); // [{ code: \"peppol\", name: \"Peppol BIS 3.0\" }, ...]\n * ```\n */\n async listTypes(): Promise<TransportType[]> {\n return this.adapter.listTransportTypes();\n }\n\n /**\n * List configured transports for this account.\n *\n * @example\n * ```ts\n * const transports = await peppol.transports.list();\n * console.log(transports); // [{ id: \"t-1\", transportTypeCode: \"peppol\", name: \"...\" }, ...]\n * ```\n */\n async list(): Promise<Transport[]> {\n return this.adapter.listTransports();\n }\n\n /**\n * Get a single transport by code.\n *\n * @example\n * ```ts\n * const transport = await peppol.transports.get(\"peppol\");\n * ```\n */\n async get(code: string): Promise<Transport> {\n return this.adapter.getTransport(code);\n }\n\n /**\n * Create a new transport.\n *\n * @example\n * ```ts\n * const transport = await peppol.transports.create({\n * transportTypeCode: \"peppol\",\n * email: \"billing@acme.com\",\n * });\n * ```\n */\n async create(input: TransportInput): Promise<Transport> {\n return this.adapter.createTransport(input);\n }\n\n /**\n * Update an existing transport.\n *\n * @example\n * ```ts\n * const transport = await peppol.transports.update(\"peppol\", { email: \"new@acme.com\" });\n * ```\n */\n async update(code: string, input: TransportUpdateInput): Promise<Transport> {\n return this.adapter.updateTransport(code, input);\n }\n\n /**\n * Delete a transport.\n *\n * @example\n * ```ts\n * await peppol.transports.delete(\"peppol\");\n * ```\n */\n async delete(code: string): Promise<void> {\n return this.adapter.deleteTransport(code);\n }\n}\n\n// ─── Webhook Helper ─────────────────────────────────────────\n\n/** Default tolerance for webhook timestamp verification (5 minutes) */\nconst DEFAULT_TOLERANCE_SECONDS = 300;\n\n/**\n * Parse and verify a webhook payload from getpeppr.\n *\n * getpeppr signs webhooks with HMAC-SHA256. The signature header format is:\n * `Getpeppr-Signature: t={timestamp},s={hmac_sha256_hex}`\n *\n * The signed payload is: `{timestamp}.{raw_json_body}`\n *\n * @example\n * ```ts\n * app.post(\"/webhooks/peppol\", (req, res) => {\n * try {\n * const event = await Peppol.webhooks.constructEvent(\n * req.body, // raw body string\n * req.headers[\"getpeppr-signature\"], // signature header\n * \"whsec_your_webhook_secret\", // your webhook secret\n * );\n * switch (event.type) {\n * case \"invoice.received\":\n * console.log(\"New invoice from:\", event.data.senderId);\n * break;\n * }\n * res.sendStatus(200);\n * } catch (err) {\n * res.status(400).send(\"Webhook verification failed\");\n * }\n * });\n * ```\n */\nexport const webhooks = {\n /**\n * Parse a webhook payload without signature verification.\n * Use `constructEvent()` for verified parsing in production.\n */\n parse(payload: unknown): WebhookEvent {\n return payload as WebhookEvent;\n },\n\n /**\n * Verify and parse a webhook payload using HMAC-SHA256 signature.\n * Throws `PeppolError` if verification fails.\n *\n * @param rawBody — The raw request body string (NOT parsed JSON)\n * @param signatureHeader — The `Getpeppr-Signature` header value\n * @param secret — Your webhook secret from getpeppr\n * @param toleranceSeconds — Max age of the webhook in seconds (default: 300 = 5 min)\n */\n async constructEvent(\n rawBody: string,\n signatureHeader: string,\n secret: string,\n toleranceSeconds?: number,\n ): Promise<WebhookEvent> {\n if (!rawBody) {\n throw new PeppolError(\"Webhook error: missing request body\");\n }\n if (!signatureHeader) {\n throw new PeppolError(\"Webhook error: missing Getpeppr-Signature header\");\n }\n if (!secret) {\n throw new PeppolError(\"Webhook error: missing webhook secret\");\n }\n\n // Parse header: t={timestamp},s={signature}\n const match = signatureHeader.match(/t=([^,]+),s=(.+)/);\n if (!match) {\n throw new PeppolError(\n \"Webhook error: invalid signature header format. Expected 't={timestamp},s={signature}'\"\n );\n }\n\n const [, timestampStr, receivedSignature] = match;\n const timestamp = Number(timestampStr);\n\n if (!Number.isFinite(timestamp)) {\n throw new PeppolError(\"Webhook error: invalid timestamp in signature header\");\n }\n\n // Check timestamp tolerance (prevent replay attacks)\n const tolerance = toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - timestamp) > tolerance) {\n throw new PeppolError(\n `Webhook error: timestamp too old or too new (received: ${timestamp}, now: ${now}, tolerance: ${tolerance}s)`\n );\n }\n\n // Compute expected signature: HMAC-SHA256(secret, \"{timestamp}.{rawBody}\")\n const signedPayload = `${timestampStr}.${rawBody}`;\n const expectedSignature = await computeHmacSha256(secret, signedPayload);\n\n // Constant-time comparison to prevent timing attacks\n if (!timingSafeEqual(expectedSignature, receivedSignature)) {\n throw new PeppolError(\"Webhook error: signature verification failed\");\n }\n\n // Parse and return the event\n try {\n const parsed = typeof rawBody === \"string\" ? JSON.parse(rawBody) : rawBody;\n return parsed as WebhookEvent;\n } catch {\n throw new PeppolError(\"Webhook error: invalid JSON payload\");\n }\n },\n};\n\n/**\n * Compute HMAC-SHA256 hex digest.\n * Uses Web Crypto API (works in Node.js 18+, Deno, Bun, browsers).\n */\nasync function computeHmacSha256(secret: string, message: string): Promise<string> {\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const signature = await crypto.subtle.sign(\"HMAC\", key, encoder.encode(message));\n return Array.from(new Uint8Array(signature))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n const len = Math.max(a.length, b.length);\n let result = a.length ^ b.length; // non-zero if lengths differ\n for (let i = 0; i < len; i++) {\n result |= (a.charCodeAt(i) || 0) ^ (b.charCodeAt(i) || 0);\n }\n return result === 0;\n}\n","/**\n * Offline Schematron-like Validation\n *\n * Reimplements the top ~25 Peppol BIS 3.0 business rules as pure TypeScript checks.\n * This is NOT a full XSD/XSLT schematron processor — it's a fast, offline validator\n * that catches the most commonly violated rules before the invoice reaches the network.\n *\n * Rules are grouped by category:\n * - BR-xx — Required field rules (EN 16931)\n * - BR-CO-xx — Calculation / cross-field consistency rules\n * - BR-S-xx — Tax category rules\n * - PEPPOL-xx — Peppol BIS 3.0 specific rules\n *\n * Design: each rule is a pure function (InvoiceInput) => SchematronViolation[].\n * No side effects, no XML, no network.\n */\n\nimport type { InvoiceInput, InvoiceLine } from \"../types/invoice.js\";\nimport { resolveUnit, getAllUnits } from \"./code-lists.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface SchematronViolation {\n /** Peppol business rule identifier (e.g., \"BR-02\", \"BR-S-01\") */\n ruleId: string;\n /** Severity: \"error\" blocks sending, \"warning\" is advisory */\n severity: \"error\" | \"warning\";\n /** Human-readable description of the violation */\n message: string;\n /** Relevant field path (e.g., \"lines[0].vatRate\") */\n field?: string;\n}\n\nexport interface SchematronResult {\n /** True if no errors (warnings are non-blocking) */\n valid: boolean;\n /** Blocking violations — invoice would be rejected */\n errors: SchematronViolation[];\n /** Advisory notices — invoice may be accepted but is suboptimal */\n warnings: SchematronViolation[];\n}\n\n// ─── Rule function type ─────────────────────────────────────────────────────────\n\ntype RuleFn = (input: InvoiceInput) => SchematronViolation[];\n\n// ─── Helpers ────────────────────────────────────────────────────────────────────\n\nfunction violation(\n ruleId: string,\n severity: \"error\" | \"warning\",\n message: string,\n field?: string,\n): SchematronViolation {\n return { ruleId, severity, message, field };\n}\n\n/** Build a Set of all known UN/ECE Rec20 unit codes (lazy singleton). */\nlet _knownUnitCodes: Set<string> | undefined;\nfunction getKnownUnitCodes(): Set<string> {\n if (!_knownUnitCodes) {\n _knownUnitCodes = new Set(getAllUnits().map((u) => u.code));\n }\n return _knownUnitCodes;\n}\n\n/** Peppol-allowed VAT category codes (UNCL 5305 subset). */\nconst VALID_VAT_CATEGORIES = new Set([\"S\", \"Z\", \"E\", \"AE\", \"K\", \"G\", \"O\", \"L\", \"M\"]);\n\n/**\n * Compute the net amount for a single invoice line.\n * Formula: (quantity * unitPrice / baseQuantity) + charges - allowances\n */\nfunction computeLineNet(line: InvoiceLine): number {\n const baseQty = line.baseQuantity ?? 1;\n if (baseQty === 0) return NaN; // Will be caught by BR-CO-10\n const baseAmount = (line.quantity * line.unitPrice) / baseQty;\n const chargeTotal = (line.charges ?? []).reduce((sum, c) => sum + c.amount, 0);\n const allowanceTotal = (line.allowances ?? []).reduce((sum, a) => sum + a.amount, 0);\n return baseAmount + chargeTotal - allowanceTotal;\n}\n\n// ─── Required Field Rules (BR-01 to BR-10) ──────────────────────────────────────\n\n/**\n * BR-01: Invoice shall have a Specification identifier.\n * Auto-pass: the gateway always sets \"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\".\n */\n// (no-op — always satisfied)\n\n/**\n * BR-02: An Invoice shall have an Invoice number.\n */\nconst br02: RuleFn = (input) => {\n if (!input.number?.trim()) {\n return [violation(\"BR-02\", \"error\", \"Invoice number is required.\", \"number\")];\n }\n return [];\n};\n\n/**\n * BR-03: An Invoice shall have an Invoice issue date.\n * The SDK defaults to today if omitted, so this is a warning.\n */\nconst br03: RuleFn = (input) => {\n if (!input.date) {\n return [\n violation(\n \"BR-03\",\n \"warning\",\n \"Invoice issue date is not set. The SDK will default to today's date.\",\n \"date\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * BR-04: An Invoice shall have an Invoice currency code.\n * Auto-pass: defaults to EUR.\n */\n// (no-op)\n\n/**\n * BR-05: An Invoice shall have an Invoice type code.\n * Auto-pass: always set (380 for invoice, 381 for credit note).\n */\n// (no-op)\n\n/**\n * BR-06: An Invoice shall have the Seller VAT identifier or tax registration.\n * The `from` field is deprecated — seller is determined by API key.\n * Only warn if `from` IS provided but has no vatNumber.\n */\nconst br06: RuleFn = (input) => {\n if (input.from && !input.from.vatNumber) {\n return [\n violation(\n \"BR-06\",\n \"warning\",\n \"Seller party has no VAT number. The gateway will use the account's VAT registration.\",\n \"from.vatNumber\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * BR-07: An Invoice shall have the Buyer name.\n */\nconst br07: RuleFn = (input) => {\n if (!input.to?.name?.trim()) {\n return [violation(\"BR-07\", \"error\", \"Buyer name is required.\", \"to.name\")];\n }\n return [];\n};\n\n/**\n * BR-08: An Invoice shall have at least one Invoice line.\n */\nconst br08: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) {\n return [violation(\"BR-08\", \"error\", \"Invoice must have at least one line item.\", \"lines\")];\n }\n return [];\n};\n\n/**\n * BR-09: An Invoice shall have the Payment due date or Payment terms.\n */\nconst br09: RuleFn = (input) => {\n if (!input.dueDate && !input.paymentTerms) {\n return [\n violation(\n \"BR-09\",\n \"warning\",\n \"Neither due date nor payment terms specified. At least one is recommended.\",\n \"dueDate\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * BR-10: An Invoice shall have the Buyer reference or Order reference.\n */\nconst br10: RuleFn = (input) => {\n if (!input.buyerReference && !input.orderReference) {\n return [\n violation(\n \"BR-10\",\n \"warning\",\n \"Neither buyerReference nor orderReference specified. Peppol BIS 3.0 requires at least one.\",\n \"buyerReference\",\n ),\n ];\n }\n return [];\n};\n\n// ─── Calculation Rules (BR-CO) ──────────────────────────────────────────────────\n\n/**\n * BR-CO-10: Sum of Invoice line net amounts = sum of (quantity x unit price / base quantity)\n * adjusted by line allowances/charges.\n *\n * Since InvoiceInput has no explicit totals, we verify each line's computation is valid\n * (no NaN, no Infinity, handles baseQuantity correctly).\n */\nconst brCo10: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const net = computeLineNet(line);\n\n if (!Number.isFinite(net)) {\n const baseQty = line.baseQuantity ?? 1;\n const detail =\n baseQty === 0\n ? \"baseQuantity is 0, causing division by zero.\"\n : \"Computed line amount is not a finite number.\";\n violations.push(\n violation(\"BR-CO-10\", \"error\", `Line ${i}: invalid net amount. ${detail}`, `lines[${i}]`),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-CO-13: Invoice total VAT amount = sum of (line net amount x VAT rate / 100) per category.\n *\n * We verify the VAT computation is valid and consistent. Since InvoiceInput has no explicit\n * VAT total field, we check that the computed amount is finite and non-negative.\n */\nconst brCo13: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) return [];\n\n let totalVat = 0;\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const net = computeLineNet(line);\n if (!Number.isFinite(net)) continue; // Already caught by BR-CO-10\n totalVat += net * (line.vatRate / 100);\n }\n\n // Include document-level allowances/charges in VAT\n for (const allowance of input.allowances ?? []) {\n totalVat -= allowance.amount * (allowance.vatRate / 100);\n }\n for (const charge of input.charges ?? []) {\n totalVat += charge.amount * (charge.vatRate / 100);\n }\n\n if (!Number.isFinite(totalVat)) {\n return [\n violation(\n \"BR-CO-13\",\n \"error\",\n \"Computed total VAT amount is not a finite number. Check line amounts and VAT rates.\",\n ),\n ];\n }\n\n if (totalVat < -0.01) {\n return [\n violation(\n \"BR-CO-13\",\n \"warning\",\n `Computed total VAT is negative (${totalVat.toFixed(2)}). This is unusual for an invoice.`,\n ),\n ];\n }\n\n return [];\n};\n\n/**\n * BR-CO-15: Invoice tax inclusive amount = Invoice total amount without VAT + Invoice total VAT amount.\n *\n * We verify the computation produces a finite, non-negative result.\n */\nconst brCo15: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) return [];\n\n let lineTotal = 0;\n let vatTotal = 0;\n\n for (const line of input.lines) {\n const net = computeLineNet(line);\n if (!Number.isFinite(net)) continue;\n lineTotal += net;\n vatTotal += net * (line.vatRate / 100);\n }\n\n // Document-level allowances/charges\n for (const allowance of input.allowances ?? []) {\n lineTotal -= allowance.amount;\n vatTotal -= allowance.amount * (allowance.vatRate / 100);\n }\n for (const charge of input.charges ?? []) {\n lineTotal += charge.amount;\n vatTotal += charge.amount * (charge.vatRate / 100);\n }\n\n const taxInclusive = lineTotal + vatTotal;\n\n if (!Number.isFinite(taxInclusive)) {\n return [\n violation(\n \"BR-CO-15\",\n \"error\",\n \"Computed tax-inclusive amount is not a finite number.\",\n ),\n ];\n }\n\n if (taxInclusive < -0.01) {\n return [\n violation(\n \"BR-CO-15\",\n \"warning\",\n `Computed tax-inclusive amount is negative (${taxInclusive.toFixed(2)}). Consider using a credit note instead.`,\n ),\n ];\n }\n\n return [];\n};\n\n/**\n * BR-CO-16: Amount due for payment = Invoice total amount with VAT - Paid amount + Rounding amount.\n *\n * Verifies payable amount is non-negative when prepaidAmount is used.\n */\nconst brCo16: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) return [];\n\n let lineTotal = 0;\n let vatTotal = 0;\n\n for (const line of input.lines) {\n const net = computeLineNet(line);\n if (!Number.isFinite(net)) continue;\n lineTotal += net;\n vatTotal += net * (line.vatRate / 100);\n }\n\n // Document-level allowances/charges\n for (const allowance of input.allowances ?? []) {\n lineTotal -= allowance.amount;\n vatTotal -= allowance.amount * (allowance.vatRate / 100);\n }\n for (const charge of input.charges ?? []) {\n lineTotal += charge.amount;\n vatTotal += charge.amount * (charge.vatRate / 100);\n }\n\n const taxInclusive = lineTotal + vatTotal;\n const prepaid = input.prepaidAmount ?? 0;\n const rounding = input.roundingAmount ?? 0;\n const payable = taxInclusive - prepaid + rounding;\n\n if (!Number.isFinite(payable)) {\n return [\n violation(\n \"BR-CO-16\",\n \"error\",\n \"Computed payable amount is not a finite number.\",\n ),\n ];\n }\n\n if (payable < -0.01) {\n return [\n violation(\n \"BR-CO-16\",\n \"warning\",\n `Computed payable amount is negative (${payable.toFixed(2)}). Prepaid amount (${prepaid}) exceeds the invoice total.`,\n ),\n ];\n }\n\n return [];\n};\n\n// ─── Tax Category Rules (BR-S) ──────────────────────────────────────────────────\n\n/**\n * BR-S-01: An Invoice that contains a line where the VAT category code is \"Standard rate\" (S)\n * shall have the VAT rate greater than zero.\n */\nconst brS01: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const category = line.vatCategory ?? \"S\"; // Default is standard rate\n if (category === \"S\" && (line.vatRate === undefined || line.vatRate <= 0)) {\n violations.push(\n violation(\n \"BR-S-01\",\n \"error\",\n `Line ${i}: standard rate (S) requires vatRate > 0, got ${line.vatRate ?? \"undefined\"}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-S-05: An Invoice that contains a line where the VAT category code is \"Zero rated\" (Z)\n * shall have the VAT rate equal to 0.\n */\nconst brS05: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.vatCategory === \"Z\" && line.vatRate !== 0) {\n violations.push(\n violation(\n \"BR-S-05\",\n \"error\",\n `Line ${i}: zero-rated (Z) requires vatRate = 0, got ${line.vatRate}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-S-06: An Invoice that contains a line where the VAT category code is \"Exempt\" (E)\n * shall have the VAT rate equal to 0.\n */\nconst brS06: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.vatCategory === \"E\" && line.vatRate !== 0) {\n violations.push(\n violation(\n \"BR-S-06\",\n \"error\",\n `Line ${i}: exempt (E) requires vatRate = 0, got ${line.vatRate}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-S-08: An Invoice that contains a line where the VAT category code is \"Reverse charge\" (AE)\n * shall have the VAT rate equal to 0.\n */\nconst brS08: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.vatCategory === \"AE\" && line.vatRate !== 0) {\n violations.push(\n violation(\n \"BR-S-08\",\n \"error\",\n `Line ${i}: reverse charge (AE) requires vatRate = 0, got ${line.vatRate}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n// ─── Peppol-Specific Rules ──────────────────────────────────────────────────────\n\n/**\n * PEPPOL-EN16931-R001: Business process MUST be provided.\n * Auto-pass: the gateway always sets \"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0\".\n */\n// (no-op)\n\n/**\n * PEPPOL-EN16931-R004: A Buyer electronic address SHALL exist.\n */\nconst peppolR004: RuleFn = (input) => {\n if (!input.to?.peppolId) {\n return [\n violation(\n \"PEPPOL-EN16931-R004\",\n \"error\",\n \"Buyer electronic address (peppolId) is required for Peppol delivery.\",\n \"to.peppolId\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * PEPPOL-EN16931-R006: VAT category code MUST follow the Peppol subset of UNCL 5305.\n * Valid codes: S, Z, E, AE, K, G, O, L, M.\n */\nconst peppolR006: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const cat = line.vatCategory;\n if (cat !== undefined && !VALID_VAT_CATEGORIES.has(cat)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R006\",\n \"error\",\n `Line ${i}: invalid VAT category \"${cat}\". Must be one of: S, Z, E, AE, K, G, O, L, M.`,\n `lines[${i}].vatCategory`,\n ),\n );\n }\n }\n\n // Also check document-level allowances/charges\n for (let i = 0; i < (input.allowances ?? []).length; i++) {\n const cat = input.allowances![i]!.vatCategory;\n if (cat !== undefined && !VALID_VAT_CATEGORIES.has(cat)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R006\",\n \"error\",\n `Allowance ${i}: invalid VAT category \"${cat}\".`,\n `allowances[${i}].vatCategory`,\n ),\n );\n }\n }\n\n for (let i = 0; i < (input.charges ?? []).length; i++) {\n const cat = input.charges![i]!.vatCategory;\n if (cat !== undefined && !VALID_VAT_CATEGORIES.has(cat)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R006\",\n \"error\",\n `Charge ${i}: invalid VAT category \"${cat}\".`,\n `charges[${i}].vatCategory`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * PEPPOL-EN16931-R080: Unit of measure MUST be coded using UN/ECE Recommendation 20.\n * Warning-level since unknown codes pass through to B2BRouter which may accept them.\n */\nconst peppolR080: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n const knownCodes = getKnownUnitCodes();\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.unit) {\n const resolved = resolveUnit(line.unit);\n if (!knownCodes.has(resolved)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R080\",\n \"warning\",\n `Line ${i}: unit \"${line.unit}\" (resolved: \"${resolved}\") is not a known UN/ECE Rec20 code. Common codes: EA, HUR, DAY, KGM.`,\n `lines[${i}].unit`,\n ),\n );\n }\n }\n // No unit specified → defaults to \"EA\" which is valid → no violation\n }\n\n return violations;\n};\n\n// ─── Rule Registry ──────────────────────────────────────────────────────────────\n\n/** All active rules in evaluation order. */\nconst ALL_RULES: readonly RuleFn[] = [\n // Required fields (BR)\n br02,\n br03,\n br06,\n br07,\n br08,\n br09,\n br10,\n // Calculations (BR-CO)\n brCo10,\n brCo13,\n brCo15,\n brCo16,\n // Tax categories (BR-S)\n brS01,\n brS05,\n brS06,\n brS08,\n // Peppol-specific\n peppolR004,\n peppolR006,\n peppolR080,\n];\n\n// ─── Main Validation Function ───────────────────────────────────────────────────\n\n/**\n * Validate an InvoiceInput against Peppol BIS 3.0 business rules (offline).\n *\n * Runs ~25 of the most commonly violated schematron rules as pure TypeScript checks.\n * No XML generation, no network calls — instant feedback.\n *\n * @param input - The invoice to validate\n * @returns Validation result with errors (blocking) and warnings (advisory)\n *\n * @example\n * ```ts\n * const result = validateSchematron({\n * number: \"INV-001\",\n * to: { name: \"Acme\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * lines: [{ description: \"Widget\", quantity: 1, unitPrice: 100, vatRate: 21 }],\n * });\n *\n * if (!result.valid) {\n * console.error(\"Validation failed:\", result.errors);\n * }\n * ```\n */\nexport function validateSchematron(input: InvoiceInput): SchematronResult {\n const errors: SchematronViolation[] = [];\n const warnings: SchematronViolation[] = [];\n\n for (const rule of ALL_RULES) {\n const violations = rule(input);\n for (const v of violations) {\n if (v.severity === \"error\") {\n errors.push(v);\n } else {\n warnings.push(v);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import type { Command } from \"commander\";\nimport { readAndValidateInvoiceJson } 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 input = readAndValidateInvoiceJson(file);\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 { exitWithError } from \"../utils/errors.js\";\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 exitWithError(\n `Error: ${filename} already exists. Use --force to overwrite.`,\n );\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 exitWithError(`Error: could not write file — ${resolved}`);\n }\n\n process.stderr.write(`${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\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:0685660237\",\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:0685660237\",\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 { readAndValidateInvoiceJson } from \"../utils/file.js\";\nimport { exitWithError } from \"../utils/errors.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 input = readAndValidateInvoiceJson(file);\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 exitWithError(`Error: XML generation failed — ${message}`);\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 { exitWithError } from \"../utils/errors.js\";\nimport {\n lookupParticipant,\n searchParticipants,\n DirectoryError,\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:0685660237)`,\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 exitWithError(\"Provide a Peppol ID or use --name to search.\");\n }\n\n // Validate --country format\n if (options.country) {\n const normalized = options.country.toUpperCase();\n if (!/^[A-Z]{2}$/.test(normalized)) {\n exitWithError(\n `Invalid country code \"${options.country}\". Must be 2 letters (e.g. BE, DE, FR).`,\n );\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 exitWithError(parsed.error);\n }\n\n let result: DirectoryMatch | null;\n\n try {\n result = await lookupParticipant(parsed.scheme, parsed.id);\n } catch (err) {\n if (err instanceof DirectoryError) {\n exitWithError(\n `${pc.red(\"\\u2717\")} Peppol Directory returned an error (HTTP ${err.status ?? \"unknown\"}). Try again later.`,\n );\n }\n exitWithError(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.`,\n );\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 exitWithError(\n `Search name must be at least 3 characters. Got: \"${options.name}\"`,\n );\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 (err) {\n if (err instanceof DirectoryError) {\n exitWithError(\n `${pc.red(\"\\u2717\")} Peppol Directory returned an error (HTTP ${err.status ?? \"unknown\"}). Try again later.`,\n );\n }\n exitWithError(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.`,\n );\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// ─── Errors ───────────────────────────────────────\n\nexport class DirectoryError extends Error {\n readonly status?: number;\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"DirectoryError\";\n this.status = status;\n }\n}\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}:${normalizeParticipantIdentifier(scheme, id)}`;\n const url = `${BASE_URL}?participant=${encodeURIComponent(participantParam)}`;\n\n const response = await fetch(url, {\n signal: AbortSignal.timeout(15_000),\n headers: { \"User-Agent\": \"@getpeppr/cli\" },\n });\n if (!response.ok) {\n throw new DirectoryError(\n `Lookup failed: HTTP ${response.status} ${response.statusText}`,\n response.status,\n );\n }\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\nfunction normalizeParticipantIdentifier(scheme: string, id: string): string {\n if (scheme === \"0208\") {\n return id.replace(/^BE(?=(?:0|1)\\d{9}$)/i, \"\");\n }\n\n return id;\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 signal: AbortSignal.timeout(15_000),\n headers: { \"User-Agent\": \"@getpeppr/cli\" },\n });\n if (!response.ok) {\n throw new DirectoryError(\n `Search failed: HTTP ${response.status} ${response.statusText}`,\n response.status,\n );\n }\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","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { Peppol } from \"@getpeppr/sdk\";\n\nimport { exitWithError } from \"../utils/errors.js\";\nimport { resolveApiKey, AuthError } from \"../lib/auth.js\";\nimport { buildPayload, MutexError } from \"../lib/send-payload.js\";\nimport { confirmInteractive } from \"../lib/confirm.js\";\nimport { pollUntilTerminal } from \"../lib/watch.js\";\nimport { formatSendResult } from \"../formatters/send-result.js\";\nimport { runValidation } from \"./validate.js\";\n\ninterface SendFlags {\n prod?: boolean;\n local?: boolean;\n key?: string;\n to?: string;\n country?: string;\n amount?: string;\n currency?: string;\n desc?: string;\n attachment?: boolean;\n watch?: boolean;\n yes?: boolean;\n validate?: boolean; // commander negates --no-validate to validate=false\n json?: boolean;\n quiet?: boolean;\n}\n\nconst API_BASE = \"https://api.getpeppr.dev/v1\";\nconst LOCAL_BASE = \"http://localhost:3001/api/v1\";\nconst DASHBOARD_BASE = \"https://console.getpeppr.dev/invoices\";\n\nexport function registerSendCommand(program: Command): void {\n program\n .command(\"send\")\n .description(\"Send an invoice to the Peppol network via getpeppr API\")\n .argument(\"[file]\", \"optional path to invoice JSON (mutex with --to/--amount/...)\")\n .option(\"--prod\", \"target production (live keys + confirmation)\")\n .option(\"--local\", \"target localhost:3001 dev server\")\n .option(\"--key <key>\", \"override API key — for CI/scripted use only; visible in `ps` and shell history. Prefer GETPEPPR_API_KEY env var.\")\n .option(\"--to <peppol-id>\", \"recipient peppol id (e.g., 9925:BE0314595348)\")\n .option(\"--country <iso>\", \"recipient ISO 3166-1 alpha-2 country override (e.g., BE)\")\n .option(\"--amount <number>\", \"line amount in major currency units (decimal allowed)\")\n .option(\"--currency <iso>\", \"ISO 4217 currency (default EUR)\")\n .option(\"--desc <text>\", \"line description\")\n .option(\"--attachment\", \"attach the test PDF\")\n .option(\"--watch\", \"poll status until delivered (60s timeout)\")\n .option(\"-y, --yes\", \"skip --prod confirmation prompt\")\n .option(\"--no-validate\", \"skip pre-validation locally\")\n .option(\"--json\", \"output JSON\")\n .option(\"--quiet\", \"exit code only, no output\")\n .action(async (file: string | undefined, flags: SendFlags) => {\n // 1. Resolve auth\n let auth;\n try {\n auth = resolveApiKey({\n flagKey: flags.key,\n forceProd: Boolean(flags.prod),\n forceLocal: Boolean(flags.local),\n });\n } catch (e) {\n if (e instanceof AuthError) {\n exitWithError(e.message);\n return;\n }\n throw e;\n }\n\n // 2. Build payload\n const overrides = {\n to: flags.to,\n country: flags.country,\n amount: flags.amount != null ? Number(flags.amount) : undefined,\n currency: flags.currency,\n description: flags.desc,\n attachment: flags.attachment,\n };\n let payload;\n try {\n payload = buildPayload({ file, overrides });\n } catch (e) {\n if (e instanceof MutexError) {\n exitWithError(e.message);\n return;\n }\n if (e instanceof Error) {\n exitWithError(e.message);\n return;\n }\n throw e;\n }\n\n // 3. Pre-validate (unless --no-validate)\n if (flags.validate !== false) {\n const result = runValidation(payload);\n if (!result.valid) {\n process.stderr.write(\n `${pc.red(\"✗\")} Pre-validation failed (${result.totalErrors} errors). Use --no-validate to skip.\\n`,\n );\n process.exit(2);\n }\n }\n\n // 4. --prod confirmation\n if (flags.prod && !flags.yes) {\n const confirmed = await confirmInteractive({\n prompt: pc.yellow(\"⚠ About to send a REAL invoice on the Peppol network. Continue?\"),\n defaultYes: false,\n });\n if (!confirmed) {\n if (!flags.quiet) process.stderr.write(\"Cancelled.\\n\");\n process.exit(0);\n }\n }\n\n // 5. Build SDK client\n const baseUrl = flags.local ? LOCAL_BASE : API_BASE;\n const client = new Peppol({ apiKey: auth.apiKey, baseUrl });\n\n // 6. Send\n let result;\n try {\n result = await client.invoices.send(payload);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n process.stderr.write(`${pc.red(\"✗\")} ${msg}\\n`);\n process.exit(1);\n }\n\n const dashboardUrl = `${DASHBOARD_BASE}/${result.id}`;\n\n // 7. --watch\n let finalStatus: string = result.status;\n let timedOut = false;\n if (flags.watch) {\n const onTransition = (s: string) => {\n if (!flags.quiet && !flags.json) {\n process.stderr.write(` ${pc.cyan(\"→\")} ${s}\\n`);\n }\n };\n try {\n const w = await pollUntilTerminal(client, result.id, {\n intervalMs: 2000,\n timeoutMs: 60_000,\n onTransition,\n });\n finalStatus = w.finalStatus;\n timedOut = w.timedOut;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n process.stderr.write(`${pc.yellow(\"⚠\")} Watch error: ${msg}\\n`);\n }\n if (timedOut) {\n process.stderr.write(\n `${pc.yellow(\"⚠\")} Timeout — invoice was sent but delivery not confirmed in 60s.\\n`,\n );\n }\n }\n\n // 8. Output\n const mode = flags.quiet ? \"quiet\" : flags.json ? \"json\" : \"formatted\";\n const output = formatSendResult(\n {\n id: result.id,\n number: payload.number,\n status: finalStatus,\n warnings: result.warnings,\n dashboardUrl,\n },\n mode,\n );\n if (output) process.stdout.write(output + \"\\n\");\n\n // 9. Exit code\n if (finalStatus === \"rejected\" || finalStatus === \"failed\") {\n process.exit(1);\n }\n process.exit(0);\n });\n}\n","import {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n statSync,\n writeFileSync,\n renameSync,\n} from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport interface Credentials {\n sandbox?: string;\n live?: string;\n}\n\nexport function getCredentialsPath(): string {\n if (platform() === \"win32\") {\n const appdata = process.env.APPDATA ?? join(homedir(), \"AppData\", \"Roaming\");\n return join(appdata, \"getpeppr\", \"credentials.json\");\n }\n // XDG-compliant default; respects $XDG_CONFIG_HOME\n const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\");\n return join(xdg, \"getpeppr\", \"credentials.json\");\n}\n\nexport function readCredentials(): Credentials | null {\n const path = getCredentialsPath();\n if (!existsSync(path)) return null;\n\n // Permission check (POSIX only)\n if (platform() !== \"win32\") {\n const stats = statSync(path);\n const mode = stats.mode & 0o777;\n if (mode !== 0o600) {\n process.stderr.write(\n `⚠ Config file mode was ${mode.toString(8)}; restoring to 600.\\n`,\n );\n chmodSync(path, 0o600);\n }\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf-8\");\n } catch {\n process.stderr.write(`⚠ Could not read config file: ${path}\\n`);\n return null;\n }\n\n try {\n const data = JSON.parse(raw) as Credentials;\n return data;\n } catch {\n process.stderr.write(`⚠ Malformed JSON in config file: ${path}\\n`);\n return null;\n }\n}\n\nexport function writeCredentials(creds: Credentials): void {\n const path = getCredentialsPath();\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n\n // Atomic write: tmp file + rename, with mode 600 (POSIX only)\n const tmpPath = `${path}.tmp`;\n const data = JSON.stringify(creds, null, 2) + \"\\n\";\n\n // Defensive: clean up any orphan tmp from a previous crashed run.\n try { rmSync(tmpPath, { force: true }); } catch { /* best effort */ }\n\n // flag: \"wx\" fails if tmp exists (eliminates mode retention) + explicit chmod as belt-and-suspenders.\n writeFileSync(tmpPath, data, { mode: 0o600, flag: \"wx\" });\n chmodSync(tmpPath, 0o600);\n\n try {\n renameSync(tmpPath, path);\n } catch (e) {\n try { rmSync(tmpPath, { force: true }); } catch { /* best effort */ }\n throw e;\n }\n}\n\nexport function deleteCredentials(): boolean {\n const path = getCredentialsPath();\n if (!existsSync(path)) return false;\n rmSync(path);\n return true;\n}\n","import { readCredentials } from \"./credentials-store.js\";\n\nexport type Environment = \"sandbox\" | \"live\";\nexport type AuthSource = \"flag\" | \"env\" | \"config\";\n\nexport interface ResolvedAuth {\n apiKey: string;\n source: AuthSource;\n environment: Environment;\n}\n\nexport interface ResolveOptions {\n flagKey?: string;\n forceProd: boolean;\n forceLocal: boolean; // reserved for Task 10 (--local flag); resolveApiKey itself does not use it\n}\n\nexport class AuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\nexport function resolveApiKey(opts: ResolveOptions): ResolvedAuth {\n const env: Environment = opts.forceProd ? \"live\" : \"sandbox\";\n\n // 1. Flag has highest priority\n if (opts.flagKey) {\n return { apiKey: opts.flagKey, source: \"flag\", environment: env };\n }\n\n // 2. Env var\n const envKey = process.env.GETPEPPR_API_KEY;\n if (envKey) {\n return { apiKey: envKey, source: \"env\", environment: env };\n }\n\n // 3. Config file\n const creds = readCredentials();\n if (creds) {\n const key = env === \"live\" ? creds.live : creds.sandbox;\n if (key) {\n return { apiKey: key, source: \"config\", environment: env };\n }\n if (env === \"live\") {\n throw new AuthError(\n `Config has no live API key. Run \\`getpeppr login\\` again with --live, or pass --key.`,\n );\n }\n }\n\n // 4. Nothing found\n throw new AuthError(\n `No API key found. Run \\`getpeppr login\\` or set GETPEPPR_API_KEY.`,\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { InvoiceInput } from \"@getpeppr/sdk\";\nimport { buildDefaultSendPayload, type SendDefaultOverrides } from \"../templates/send-default.js\";\n\nexport class MutexError extends Error {\n constructor() {\n super(\"Cannot combine custom file with override flags. Use one or the other.\");\n this.name = \"MutexError\";\n }\n}\n\nexport interface BuildPayloadOptions {\n file?: string;\n overrides?: SendDefaultOverrides;\n}\n\nfunction hasOverrides(o?: SendDefaultOverrides): boolean {\n if (!o) return false;\n // Use `!= null` for amount (handles 0) and explicit string-emptiness check for `to`.\n // `attachment: false` is the default behaviour, so we treat it as \"no override expressed\".\n // `attachment: true` is the only way to opt into the attachment override.\n return Boolean(\n (o.to != null && o.to !== \"\") ||\n (o.country != null && o.country !== \"\") ||\n o.amount != null ||\n o.currency ||\n o.description ||\n o.attachment === true,\n );\n}\n\nexport function buildPayload(opts: BuildPayloadOptions): InvoiceInput {\n if (opts.file && hasOverrides(opts.overrides)) {\n throw new MutexError();\n }\n\n if (opts.file) {\n const absPath = resolve(opts.file);\n if (!existsSync(absPath)) {\n throw new Error(`Error: file not found — ${absPath}`);\n }\n let raw: string;\n try {\n raw = readFileSync(absPath, \"utf-8\");\n } catch {\n throw new Error(`Error: could not read file — ${absPath}`);\n }\n try {\n return JSON.parse(raw) as InvoiceInput;\n } catch {\n throw new Error(`Error: invalid JSON in file — ${absPath}`);\n }\n }\n\n return buildDefaultSendPayload(opts.overrides);\n}\n","import type { InvoiceInput, PeppolId, CountryCode } from \"@getpeppr/sdk\";\n\n// Minimal valid PDF (Storecove validates content). Canonical source is\n// packages/sdk/scripts/send-test-invoice.ts — if that script's PDF is ever\n// updated, this duplicate must be kept in sync. The scripts/ directory is\n// excluded from SDK tsconfig so cross-package import isn't possible.\nconst MINIMAL_PDF = `%PDF-1.0\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj\nxref\n0 4\n0000000000 65535 f\n0000000009 00000 n\n0000000058 00000 n\n0000000115 00000 n\ntrailer<</Size 4/Root 1 0 R>>\nstartxref\n190\n%%EOF`;\n\nexport const MINIMAL_TEST_PDF_BASE64 = Buffer.from(MINIMAL_PDF).toString(\"base64\");\n\nexport interface SendDefaultOverrides {\n to?: string;\n country?: string;\n amount?: number;\n currency?: string;\n description?: string;\n attachment?: boolean;\n}\n\nconst SCHEME_COUNTRY_DEFAULTS: Record<string, CountryCode> = {\n \"0009\": \"FR\" as CountryCode,\n \"0204\": \"DE\" as CountryCode,\n \"0208\": \"BE\" as CountryCode,\n \"9925\": \"BE\" as CountryCode,\n};\n\nfunction deriveCountryFromPeppolId(peppolId: PeppolId): CountryCode {\n const [scheme, identifier = \"\"] = peppolId.split(\":\");\n const alphaPrefix = identifier.slice(0, 2);\n\n if (/^[A-Za-z]{2}$/.test(alphaPrefix)) {\n return alphaPrefix.toUpperCase() as CountryCode;\n }\n\n return SCHEME_COUNTRY_DEFAULTS[scheme] ?? (\"BE\" as CountryCode);\n}\n\nexport function buildDefaultSendPayload(overrides: SendDefaultOverrides = {}): InvoiceInput {\n const today = new Date();\n const due = new Date(today.getTime() + 30 * 86400000);\n const isoToday = today.toISOString().slice(0, 10);\n const isoDue = due.toISOString().slice(0, 10);\n\n // TODO(Task 10 send command): validate scheme:id format upstream before calling.\n // Cast is safe assuming caller passes valid Peppol ID format (XXXX:YYYYYY).\n const peppolId = (overrides.to ?? \"9925:BE0314595348\") as PeppolId; // SPF Economie BE — accepts test invoices\n const amount = overrides.amount ?? 100;\n const currency = overrides.currency ?? \"EUR\";\n const description = overrides.description ?? \"Test service from getpeppr\";\n\n // Unique invoice number: TEST-{base36 timestamp}-{4-char random hex}.\n // The random suffix guarantees uniqueness even when two calls land within the same millisecond.\n const randomSuffix = Math.floor(Math.random() * 0x10000)\n .toString(16)\n .toUpperCase()\n .padStart(4, \"0\");\n const number = `TEST-${Date.now().toString(36).toUpperCase()}-${randomSuffix}`;\n\n // Best-effort country derivation from Peppol ID. Some Belgian 0208 IDs are bare\n // enterprise numbers (e.g. 0208:0738836782), so fall back to the scheme mapping.\n // CountryCode is `\"BE\" | \"FR\" | ... | (string & {})` so any string is accepted.\n const country = overrides.country != null\n ? overrides.country.toUpperCase() as CountryCode\n : deriveCountryFromPeppolId(peppolId);\n\n const payload: InvoiceInput = {\n number,\n date: isoToday,\n dueDate: isoDue,\n currency,\n to: {\n name: peppolId === \"9925:BE0314595348\" ? \"SPF Economie (TEST)\" : \"Test Recipient\",\n peppolId,\n country,\n street: \"Rue de la Loi 1\",\n city: \"Brussels\",\n postalCode: \"1000\",\n },\n lines: [\n {\n description,\n quantity: 1,\n unitPrice: amount,\n vatRate: 0,\n // vatCategory \"O\" = \"Services outside scope of tax\" (UBL 2.1 / EN 16931).\n // Public entities (SPF Economie) are VAT-exempt. No `taxExemptReason` field\n // exists in InvoiceLine — Storecove derives exemption from the category code.\n // If sandbox returns 422 on this combination, fallback is vatRate: 21 + vatCategory: \"S\".\n vatCategory: \"O\",\n },\n ],\n };\n\n if (overrides.attachment) {\n payload.attachments = [\n {\n id: \"ATT-001\",\n description: \"Test document\",\n filename: \"test.pdf\",\n mimeType: \"application/pdf\",\n content: MINIMAL_TEST_PDF_BASE64,\n },\n ];\n }\n\n return payload;\n}\n","import type { Readable, Writable } from \"node:stream\";\nimport { createInterface } from \"node:readline\";\n\nexport interface ConfirmOptions {\n prompt: string;\n defaultYes: boolean;\n stdin?: Readable;\n stdout?: Writable;\n}\n\nexport async function confirmInteractive(opts: ConfirmOptions): Promise<boolean> {\n const stdin = (opts.stdin ?? process.stdin) as Readable & { isTTY?: boolean };\n const stdout = opts.stdout ?? process.stdout;\n\n // Non-TTY (CI, piped, vitest) → fall back to default.\n // Treat any non-true value (false, undefined) as non-TTY.\n if (stdin.isTTY !== true) {\n return opts.defaultYes;\n }\n\n const suffix = opts.defaultYes ? \"[Y/n]\" : \"[y/N]\";\n return new Promise<boolean>((resolve) => {\n const rl = createInterface({ input: stdin, output: stdout });\n let settled = false;\n\n rl.question(`${opts.prompt} ${suffix} `, (answer) => {\n settled = true;\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === \"\") return resolve(opts.defaultYes);\n if (trimmed === \"y\" || trimmed === \"yes\") return resolve(true);\n if (trimmed === \"n\" || trimmed === \"no\") return resolve(false);\n // Unrecognized input → defaultYes (lenient)\n return resolve(opts.defaultYes);\n });\n\n // Guard: if stdin closes without newline (Ctrl+D, EOF), question callback\n // never fires. Resolve to defaultYes consistent with lenient-fallback policy.\n rl.once(\"close\", () => {\n if (!settled) resolve(opts.defaultYes);\n });\n });\n}\n","export type TerminalStatus = \"delivered\" | \"accepted\" | \"rejected\" | \"failed\";\n\nconst TERMINAL_STATES = new Set<TerminalStatus>([\n \"delivered\",\n \"accepted\",\n \"rejected\",\n \"failed\",\n]);\n\nexport interface WatchOptions {\n intervalMs?: number;\n timeoutMs?: number;\n onTransition?: (status: string) => void;\n}\n\nexport interface WatchResult {\n finalStatus: string;\n timedOut: boolean;\n}\n\ninterface StatusFetcher {\n invoices: { getStatus: (id: string) => Promise<{ status: string }> };\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\nexport async function pollUntilTerminal(\n client: StatusFetcher,\n documentId: string,\n options: WatchOptions = {},\n): Promise<WatchResult> {\n const intervalMs = options.intervalMs ?? 2000;\n const timeoutMs = options.timeoutMs ?? 60_000;\n const start = Date.now();\n\n let lastStatus = \"\";\n\n while (Date.now() - start < timeoutMs) {\n const { status } = await client.invoices.getStatus(documentId);\n\n if (status !== lastStatus) {\n options.onTransition?.(status);\n lastStatus = status;\n }\n\n if (TERMINAL_STATES.has(status as TerminalStatus)) {\n return { finalStatus: status, timedOut: false };\n }\n\n await sleep(intervalMs);\n }\n\n return { finalStatus: lastStatus, timedOut: true };\n}\n","import pc from \"picocolors\";\n\nexport interface SendResultPayload {\n id: string;\n number: string;\n status: string;\n warnings?: { message: string }[];\n dashboardUrl: string;\n}\n\nexport type OutputMode = \"formatted\" | \"json\" | \"quiet\";\n\nexport function formatSendResult(result: SendResultPayload, mode: OutputMode): string {\n if (mode === \"quiet\") return \"\";\n\n if (mode === \"json\") {\n return JSON.stringify(result, null, 2);\n }\n\n // formatted\n const lines: string[] = [];\n lines.push(`${pc.green(\"✓\")} Sent ${pc.bold(result.number)}`);\n lines.push(` id: ${result.id}`);\n lines.push(` Status: ${pc.cyan(result.status)}`);\n lines.push(` Track: ${pc.dim(result.dashboardUrl)}`);\n\n const wCount = result.warnings?.length ?? 0;\n if (wCount > 0) {\n lines.push(` ${pc.yellow(`${wCount} warning${wCount === 1 ? \"\" : \"s\"}`)}`);\n for (const w of result.warnings ?? []) {\n lines.push(` ${pc.yellow(\"⚠\")} ${w.message}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","import { createInterface } from \"node:readline\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { exitWithError } from \"../utils/errors.js\";\nimport {\n getCredentialsPath,\n readCredentials,\n writeCredentials,\n} from \"../lib/credentials-store.js\";\n\ninterface LoginFlags {\n key?: string;\n sandbox?: boolean;\n live?: boolean;\n}\n\nasync function promptMaskedKey(envLabel: string): Promise<string> {\n if (process.stdin.isTTY !== true) {\n exitWithError(\"Error: --key flag required when stdin is not a TTY (CI mode).\");\n }\n\n process.stdout.write(`Paste your ${envLabel} API key (input hidden): `);\n\n return new Promise<string>((resolve) => {\n let buffer = \"\";\n const onData = (chunk: Buffer) => {\n const c = chunk.toString(\"utf-8\");\n if (c === \"\\n\" || c === \"\\r\" || c === \"\\r\\n\") {\n process.stdin.setRawMode(false);\n process.stdin.removeListener(\"data\", onData);\n process.stdin.pause();\n process.stdout.write(\"\\n\");\n resolve(buffer);\n return;\n }\n if (c === \"\\x03\") {\n // Ctrl-C in raw mode: SIGINT is disabled, byte arrives as ETX (0x03)\n process.stdin.setRawMode(false);\n process.stdin.removeListener(\"data\", onData);\n process.stdin.pause();\n process.stdout.write(\"\\n\");\n process.exit(130);\n }\n if (c === \"\\x7f\" || c === \"\\b\") {\n // Backspace: POSIX terminals send DEL (0x7f), some send BS (0x08 / \"\\b\")\n buffer = buffer.slice(0, -1);\n return;\n }\n buffer += c;\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on(\"data\", onData);\n });\n}\n\nasync function promptEnvironment(): Promise<\"sandbox\" | \"live\"> {\n if (process.stdin.isTTY !== true) return \"sandbox\";\n\n return new Promise<\"sandbox\" | \"live\">((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(\"Environment? (s)andbox / (l)ive [sandbox]: \", (answer) => {\n rl.close();\n const a = answer.trim().toLowerCase();\n if (a === \"l\" || a === \"live\") return resolve(\"live\");\n return resolve(\"sandbox\");\n });\n });\n}\n\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .description(\"Save a getpeppr API key to ~/.config/getpeppr/credentials.json\")\n .option(\"--key <key>\", \"API key — for CI/scripted use only; visible in `ps` and shell history. Prefer the interactive prompt or GETPEPPR_API_KEY env var.\")\n .option(\"--sandbox\", \"store as sandbox key (default)\")\n .option(\"--live\", \"store as live (production) key\")\n .action(async (flags: LoginFlags) => {\n if (!flags.live && !flags.sandbox && process.stdin.isTTY !== true) {\n exitWithError(\"Error: --sandbox or --live required when stdin is not a TTY (CI mode).\");\n }\n\n let env: \"sandbox\" | \"live\";\n if (flags.live) env = \"live\";\n else if (flags.sandbox) env = \"sandbox\";\n else env = await promptEnvironment();\n\n let key: string;\n if (flags.key) {\n key = flags.key;\n } else {\n key = (await promptMaskedKey(env)).trim();\n if (!key) exitWithError(\"Error: empty API key.\");\n }\n\n const existing = readCredentials() ?? {};\n const next = { ...existing, [env]: key };\n writeCredentials(next);\n\n const path = getCredentialsPath();\n process.stderr.write(\n `${pc.green(\"✓\")} Saved ${env} key to ${path} (mode 600)\\n`,\n );\n });\n}\n","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { deleteCredentials, getCredentialsPath } from \"../lib/credentials-store.js\";\n\nexport function registerLogoutCommand(program: Command): void {\n program\n .command(\"logout\")\n .description(\"Remove ~/.config/getpeppr/credentials.json\")\n .action(() => {\n const path = getCredentialsPath();\n const removed = deleteCredentials();\n if (removed) {\n process.stderr.write(`${pc.green(\"✓\")} Removed ${path}\\n`);\n } else {\n process.stderr.write(`No credentials to remove (${path})\\n`);\n }\n process.exit(0);\n });\n}\n"],"mappings":"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","names":["warn","resolve","error","program","existsSync","resolve","pc","program","resolve","existsSync","pc","writeFileSync","pc","program","writeFileSync","pc","pc","pc","program","pc","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","resolve","resolve","existsSync","readFileSync","resolve","sleep","pc","program","result","pc","createInterface","pc","resolve","createInterface","program","pc","pc","program","pc","require"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/file.ts","../src/utils/errors.ts","../src/formatters/validation.ts","../../sdk/src/core/ubl-builder.ts","../../sdk/src/core/country-rules.ts","../../sdk/src/core/code-lists.ts","../../sdk/src/core/validator.ts","../../sdk/src/version.ts","../../sdk/src/core/client.ts","../../sdk/src/core/schematron.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","../src/commands/send.ts","../src/lib/credentials-store.ts","../src/lib/auth.ts","../src/lib/send-payload.ts","../src/templates/send-default.ts","../src/lib/confirm.ts","../src/lib/watch.ts","../src/formatters/send-result.ts","../src/commands/login.ts","../src/commands/logout.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\";\nimport { registerSendCommand } from \"./commands/send.js\";\nimport { registerLoginCommand } from \"./commands/login.js\";\nimport { registerLogoutCommand } from \"./commands/logout.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);\nregisterSendCommand(program);\nregisterLoginCommand(program);\nregisterLogoutCommand(program);\n\nprogram.parse();\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { InvoiceInput } from \"@getpeppr/sdk\";\nimport { exitWithError } from \"./errors.js\";\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\nexport function readAndValidateInvoiceJson(filePath: string): InvoiceInput {\n const parseResult = readJsonFile(filePath);\n if (!parseResult.ok) {\n exitWithError(parseResult.error);\n }\n\n if (\n typeof parseResult.data !== \"object\" ||\n parseResult.data === null ||\n Array.isArray(parseResult.data)\n ) {\n exitWithError(\n \"Error: JSON file must contain an object, not an array or primitive\",\n );\n }\n\n return parseResult.data as InvoiceInput;\n}\n","export function exitWithError(message: string, code = 2): never {\n process.stderr.write(message + \"\\n\");\n process.exit(code);\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","/**\n * UBL XML Builder\n *\n * Converts our clean JSON invoice format to Peppol BIS 3.0 compliant UBL 2.1 XML.\n * This is the core abstraction that hides XML complexity from developers.\n *\n * Reference: https://docs.peppol.eu/poacc/billing/3.0/\n */\n\nimport type { InvoiceInput, CreditNoteInput, InvoiceLine, Party, Delivery, AllowanceCharge, Attachment, InvoicePeriod } from \"../types/invoice.js\";\n\nconst UBL_NS = \"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\";\nconst CAC_NS = \"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2\";\nconst CBC_NS = \"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2\";\nconst CREDIT_NOTE_NS = \"urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2\";\n\n// Peppol BIS 3.0 customization and profile IDs\nconst PEPPOL_CUSTOMIZATION_ID =\n \"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\";\nconst PEPPOL_PROFILE_ID = \"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0\";\n\n/** Default unit of measure */\nconst DEFAULT_UNIT = \"EA\";\n\n/** Default payment means code (30 = credit transfer) */\nconst DEFAULT_PAYMENT_MEANS = 30;\n\n/** Map human-readable unit names to UN/ECE Recommendation 20 codes */\nconst UNIT_CODE_MAP: Record<string, string> = {\n each: \"EA\", piece: \"EA\", pieces: \"EA\",\n hour: \"HUR\", hours: \"HUR\",\n day: \"DAY\", days: \"DAY\",\n week: \"WEE\", weeks: \"WEE\",\n month: \"MON\", months: \"MON\",\n year: \"ANN\", years: \"ANN\",\n kilogram: \"KGM\", kg: \"KGM\",\n meter: \"MTR\", metre: \"MTR\",\n liter: \"LTR\", litre: \"LTR\",\n unit: \"C62\", units: \"C62\",\n set: \"SET\", sets: \"SET\",\n pack: \"PK\", packs: \"PK\",\n};\n\n/**\n * Resolve a human-readable unit name to its UN/ECE Recommendation 20 code.\n * If already a valid UBL code (2-3 uppercase chars) or unknown, passes through unchanged.\n */\nfunction resolveUnitCode(unit: string): string {\n return UNIT_CODE_MAP[unit.toLowerCase()] ?? unit;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction formatDate(dateStr?: string): string {\n if (!dateStr) {\n return new Date().toISOString().split(\"T\")[0]!;\n }\n // Accept ISO 8601 date or datetime\n return dateStr.split(\"T\")[0]!;\n}\n\nfunction formatAmount(amount: number): string {\n return amount.toFixed(2);\n}\n\n/** Round to 2 decimal places to prevent IEEE 754 accumulation errors */\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction parsePeppolId(peppolId: string): { scheme: string; id: string } {\n const scheme = peppolId.split(\":\")[0]!;\n const id = peppolId.split(\":\").slice(1).join(\":\");\n return { scheme, id };\n}\n\nfunction buildPartyXml(party: Party, role: \"AccountingSupplierParty\" | \"AccountingCustomerParty\"): string {\n const { scheme: endpointScheme, id: endpointId } = parsePeppolId(party.peppolId);\n\n return `\n <cac:${role}>\n <cac:Party>\n <cbc:EndpointID schemeID=\"${escapeXml(endpointScheme)}\">${escapeXml(endpointId)}</cbc:EndpointID>\n <cac:PartyIdentification>\n <cbc:ID schemeID=\"${escapeXml(endpointScheme)}\">${escapeXml(endpointId)}</cbc:ID>\n </cac:PartyIdentification>\n <cac:PartyName>\n <cbc:Name>${escapeXml(party.name)}</cbc:Name>\n </cac:PartyName>\n <cac:PostalAddress>\n ${party.street ? `<cbc:StreetName>${escapeXml(party.street)}</cbc:StreetName>` : \"\"}\n ${party.city ? `<cbc:CityName>${escapeXml(party.city)}</cbc:CityName>` : \"\"}\n ${party.postalCode ? `<cbc:PostalZone>${escapeXml(party.postalCode)}</cbc:PostalZone>` : \"\"}\n <cac:Country>\n <cbc:IdentificationCode>${escapeXml(party.country)}</cbc:IdentificationCode>\n </cac:Country>\n </cac:PostalAddress>\n ${\n party.vatNumber\n ? `<cac:PartyTaxScheme>\n <cbc:CompanyID>${escapeXml(party.vatNumber)}</cbc:CompanyID>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:PartyTaxScheme>`\n : \"\"\n }\n <cac:PartyLegalEntity>\n <cbc:RegistrationName>${escapeXml(party.name)}</cbc:RegistrationName>\n ${party.companyId ? `<cbc:CompanyID>${escapeXml(party.companyId)}</cbc:CompanyID>` : \"\"}\n </cac:PartyLegalEntity>\n ${(party.contactName || party.phone || party.email)\n ? `<cac:Contact>\n ${party.contactName ? `<cbc:Name>${escapeXml(party.contactName)}</cbc:Name>` : \"\"}\n ${party.phone ? `<cbc:Telephone>${escapeXml(party.phone)}</cbc:Telephone>` : \"\"}\n ${party.email ? `<cbc:ElectronicMail>${escapeXml(party.email)}</cbc:ElectronicMail>` : \"\"}\n </cac:Contact>`\n : \"\"\n }\n </cac:Party>\n </cac:${role}>`;\n}\n\nfunction buildPayeePartyXml(party: Party): string {\n const { scheme, id } = parsePeppolId(party.peppolId);\n\n return `\n <cac:PayeeParty>\n <cac:PartyIdentification>\n <cbc:ID schemeID=\"${escapeXml(scheme)}\">${escapeXml(id)}</cbc:ID>\n </cac:PartyIdentification>\n <cac:PartyName>\n <cbc:Name>${escapeXml(party.name)}</cbc:Name>\n </cac:PartyName>\n ${party.companyId\n ? `<cac:PartyLegalEntity>\n <cbc:RegistrationName>${escapeXml(party.name)}</cbc:RegistrationName>\n <cbc:CompanyID>${escapeXml(party.companyId)}</cbc:CompanyID>\n </cac:PartyLegalEntity>`\n : \"\"\n }\n </cac:PayeeParty>`;\n}\n\nfunction buildTaxRepresentativePartyXml(party: Party): string {\n const parts: string[] = [\n \" <cac:TaxRepresentativeParty>\",\n \" <cac:PartyName>\",\n ` <cbc:Name>${escapeXml(party.name)}</cbc:Name>`,\n \" </cac:PartyName>\",\n ];\n\n // PostalAddress\n parts.push(\" <cac:PostalAddress>\");\n if (party.street) {\n parts.push(` <cbc:StreetName>${escapeXml(party.street)}</cbc:StreetName>`);\n }\n if (party.city) {\n parts.push(` <cbc:CityName>${escapeXml(party.city)}</cbc:CityName>`);\n }\n if (party.postalCode) {\n parts.push(` <cbc:PostalZone>${escapeXml(party.postalCode)}</cbc:PostalZone>`);\n }\n parts.push(\" <cac:Country>\");\n parts.push(` <cbc:IdentificationCode>${escapeXml(party.country)}</cbc:IdentificationCode>`);\n parts.push(\" </cac:Country>\");\n parts.push(\" </cac:PostalAddress>\");\n\n // PartyTaxScheme (vatNumber → CompanyID)\n if (party.vatNumber) {\n parts.push(\" <cac:PartyTaxScheme>\");\n parts.push(` <cbc:CompanyID>${escapeXml(party.vatNumber)}</cbc:CompanyID>`);\n parts.push(\" <cac:TaxScheme>\");\n parts.push(\" <cbc:ID>VAT</cbc:ID>\");\n parts.push(\" </cac:TaxScheme>\");\n parts.push(\" </cac:PartyTaxScheme>\");\n }\n\n parts.push(\" </cac:TaxRepresentativeParty>\");\n return parts.join(\"\\n\");\n}\n\nfunction buildAttachmentXml(attachment: Attachment): string {\n const parts: string[] = [\n \"<cac:AdditionalDocumentReference>\",\n ` <cbc:ID>${escapeXml(attachment.id)}</cbc:ID>`,\n ];\n\n if (attachment.description) {\n parts.push(` <cbc:DocumentDescription>${escapeXml(attachment.description)}</cbc:DocumentDescription>`);\n }\n\n if (attachment.content || attachment.url) {\n parts.push(\" <cac:Attachment>\");\n if (attachment.content && attachment.mimeType && attachment.filename) {\n parts.push(\n ` <cbc:EmbeddedDocumentBinaryObject mimeCode=\"${escapeXml(attachment.mimeType)}\" filename=\"${escapeXml(attachment.filename)}\">${attachment.content}</cbc:EmbeddedDocumentBinaryObject>`,\n );\n } else if (attachment.url) {\n parts.push(\n ` <cac:ExternalReference>\\n <cbc:URI>${escapeXml(attachment.url)}</cbc:URI>\\n </cac:ExternalReference>`,\n );\n }\n parts.push(\" </cac:Attachment>\");\n }\n\n parts.push(\"</cac:AdditionalDocumentReference>\");\n return parts.join(\"\\n \");\n}\n\nfunction buildInvoicePeriodXml(period: InvoicePeriod): string {\n const parts: string[] = [\"<cac:InvoicePeriod>\"];\n if (period.startDate) {\n parts.push(` <cbc:StartDate>${formatDate(period.startDate)}</cbc:StartDate>`);\n }\n if (period.endDate) {\n parts.push(` <cbc:EndDate>${formatDate(period.endDate)}</cbc:EndDate>`);\n }\n parts.push(\"</cac:InvoicePeriod>\");\n return parts.join(\"\\n \");\n}\n\nfunction buildDeliveryXml(delivery: Delivery): string {\n const parts: string[] = [\"<cac:Delivery>\"];\n\n if (delivery.date) {\n parts.push(` <cbc:ActualDeliveryDate>${formatDate(delivery.date)}</cbc:ActualDeliveryDate>`);\n }\n\n if (delivery.locationId || delivery.address) {\n parts.push(\" <cac:DeliveryLocation>\");\n if (delivery.locationId) {\n parts.push(` <cbc:ID>${escapeXml(delivery.locationId)}</cbc:ID>`);\n }\n if (delivery.address) {\n parts.push(\" <cac:Address>\");\n if (delivery.address.street) {\n parts.push(` <cbc:StreetName>${escapeXml(delivery.address.street)}</cbc:StreetName>`);\n }\n if (delivery.address.city) {\n parts.push(` <cbc:CityName>${escapeXml(delivery.address.city)}</cbc:CityName>`);\n }\n if (delivery.address.postalCode) {\n parts.push(` <cbc:PostalZone>${escapeXml(delivery.address.postalCode)}</cbc:PostalZone>`);\n }\n parts.push(` <cac:Country>\\n <cbc:IdentificationCode>${escapeXml(delivery.address.country)}</cbc:IdentificationCode>\\n </cac:Country>`);\n parts.push(\" </cac:Address>\");\n }\n parts.push(\" </cac:DeliveryLocation>\");\n }\n\n parts.push(\"</cac:Delivery>\");\n return parts.join(\"\\n \");\n}\n\nfunction buildDocumentAllowanceChargeXml(\n item: AllowanceCharge,\n isCharge: boolean,\n currency: string,\n): string {\n const vatCategory = item.vatCategory ?? \"S\";\n return `\n <cac:AllowanceCharge>\n <cbc:ChargeIndicator>${isCharge}</cbc:ChargeIndicator>\n <cbc:AllowanceChargeReason>${escapeXml(item.reason)}</cbc:AllowanceChargeReason>\n <cbc:Amount currencyID=\"${escapeXml(currency)}\">${formatAmount(item.amount)}</cbc:Amount>\n <cac:TaxCategory>\n <cbc:ID>${vatCategory}</cbc:ID>\n <cbc:Percent>${item.vatRate}</cbc:Percent>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:TaxCategory>\n </cac:AllowanceCharge>`;\n}\n\nfunction buildLineAllowanceChargeXml(\n reason: string,\n amount: number,\n isCharge: boolean,\n currency: string,\n): string {\n return `\n <cac:AllowanceCharge>\n <cbc:ChargeIndicator>${isCharge}</cbc:ChargeIndicator>\n <cbc:AllowanceChargeReason>${escapeXml(reason)}</cbc:AllowanceChargeReason>\n <cbc:Amount currencyID=\"${escapeXml(currency)}\">${formatAmount(amount)}</cbc:Amount>\n </cac:AllowanceCharge>`;\n}\n\nfunction calculateLineExtensionAmount(line: InvoiceLine): number {\n const base = line.quantity * line.unitPrice;\n const lineAllowances = (line.allowances ?? []).reduce((sum, a) => sum + a.amount, 0);\n const lineCharges = (line.charges ?? []).reduce((sum, c) => sum + c.amount, 0);\n return base - lineAllowances + lineCharges;\n}\n\ntype LineType = \"InvoiceLine\" | \"CreditNoteLine\";\ntype QuantityType = \"InvoicedQuantity\" | \"CreditedQuantity\";\n\nfunction buildDocumentLineXml(\n line: InvoiceLine,\n index: number,\n currency: string,\n lineTag: LineType,\n qtyTag: QuantityType,\n): string {\n const lineTotal = calculateLineExtensionAmount(line);\n const unit = resolveUnitCode(line.unit ?? DEFAULT_UNIT);\n const vatCategory = line.vatCategory ?? \"S\";\n\n const lineAllowancesXml = (line.allowances ?? [])\n .map((a) => buildLineAllowanceChargeXml(a.reason, a.amount, false, currency))\n .join(\"\");\n const lineChargesXml = (line.charges ?? [])\n .map((c) => buildLineAllowanceChargeXml(c.reason, c.amount, true, currency))\n .join(\"\");\n\n return `\n <cac:${lineTag}>\n <cbc:ID>${index + 1}</cbc:ID>\n ${line.accountingCost ? `<cbc:AccountingCost>${escapeXml(line.accountingCost)}</cbc:AccountingCost>` : \"\"}\n <cbc:${qtyTag} unitCode=\"${escapeXml(unit)}\">${Number(line.quantity.toFixed(6))}</cbc:${qtyTag}>\n <cbc:LineExtensionAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(lineTotal)}</cbc:LineExtensionAmount>\n ${lineAllowancesXml}${lineChargesXml}\n <cac:Item>\n <cbc:Name>${escapeXml(line.description)}</cbc:Name>\n ${\n line.itemId\n ? `<cac:SellersItemIdentification>\n <cbc:ID>${escapeXml(line.itemId)}</cbc:ID>\n </cac:SellersItemIdentification>`\n : \"\"\n }\n <cac:ClassifiedTaxCategory>\n <cbc:ID>${vatCategory}</cbc:ID>\n <cbc:Percent>${line.vatRate}</cbc:Percent>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:ClassifiedTaxCategory>\n ${\n line.standardItemId\n ? `<cac:StandardItemIdentification>\n <cbc:ID schemeID=\"${escapeXml(line.standardItemScheme ?? \"0160\")}\">${escapeXml(line.standardItemId)}</cbc:ID>\n </cac:StandardItemIdentification>`\n : \"\"\n }\n ${\n line.commodityCode && line.commodityScheme\n ? `<cac:CommodityClassification>\n <cbc:ItemClassificationCode listID=\"${escapeXml(line.commodityScheme)}\">${escapeXml(line.commodityCode)}</cbc:ItemClassificationCode>\n </cac:CommodityClassification>`\n : \"\"\n }\n ${(line.properties ?? []).map(\n (p) => `<cac:AdditionalItemProperty>\n <cbc:Name>${escapeXml(p.name)}</cbc:Name>\n <cbc:Value>${escapeXml(p.value)}</cbc:Value>\n </cac:AdditionalItemProperty>`\n ).join(\"\\n \")}\n </cac:Item>\n <cac:Price>\n <cbc:PriceAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(line.unitPrice)}</cbc:PriceAmount>\n ${line.baseQuantity != null ? `<cbc:BaseQuantity unitCode=\"${escapeXml(resolveUnitCode(line.baseQuantityUnit ?? line.unit ?? DEFAULT_UNIT))}\">${line.baseQuantity}</cbc:BaseQuantity>` : \"\"}\n </cac:Price>\n </cac:${lineTag}>`;\n}\n\nfunction buildInvoiceLineXml(line: InvoiceLine, index: number, currency: string): string {\n return buildDocumentLineXml(line, index, currency, \"InvoiceLine\", \"InvoicedQuantity\");\n}\n\ninterface TaxSubtotal {\n vatRate: number;\n vatCategory: string;\n taxableAmount: number;\n taxAmount: number;\n}\n\nfunction calculateTaxSubtotals(\n lines: InvoiceLine[],\n allowances?: AllowanceCharge[],\n charges?: AllowanceCharge[],\n): TaxSubtotal[] {\n const groups = new Map<string, TaxSubtotal>();\n\n function addToGroup(vatCategory: string, vatRate: number, amount: number) {\n const key = `${vatCategory}-${vatRate}`;\n const lineTax = round2(amount * (vatRate / 100));\n const existing = groups.get(key);\n if (existing) {\n existing.taxableAmount = round2(existing.taxableAmount + amount);\n existing.taxAmount = round2(existing.taxAmount + lineTax);\n } else {\n groups.set(key, {\n vatRate,\n vatCategory,\n taxableAmount: amount,\n taxAmount: lineTax,\n });\n }\n }\n\n for (const line of lines) {\n addToGroup(line.vatCategory ?? \"S\", line.vatRate, calculateLineExtensionAmount(line));\n }\n\n for (const a of allowances ?? []) {\n addToGroup(a.vatCategory ?? \"S\", a.vatRate, -a.amount);\n }\n\n for (const c of charges ?? []) {\n addToGroup(c.vatCategory ?? \"S\", c.vatRate, c.amount);\n }\n\n return Array.from(groups.values());\n}\n\n// ─── Shared document-level XML fragments ───────────────────\n\ninterface DocumentTotals {\n lineExtensionAmount: number;\n allowanceTotalAmount: number;\n chargeTotalAmount: number;\n taxExclusiveAmount: number;\n totalTax: number;\n taxInclusiveAmount: number;\n payableAmount: number;\n taxSubtotals: TaxSubtotal[];\n}\n\nfunction calculateDocumentTotals(\n lines: InvoiceLine[],\n allowances?: AllowanceCharge[],\n charges?: AllowanceCharge[],\n): DocumentTotals {\n const taxSubtotals = calculateTaxSubtotals(lines, allowances, charges);\n const lineExtensionAmount = lines.reduce(\n (sum, line) => sum + calculateLineExtensionAmount(line),\n 0,\n );\n const allowanceTotalAmount = (allowances ?? []).reduce((sum, a) => sum + a.amount, 0);\n const chargeTotalAmount = (charges ?? []).reduce((sum, c) => sum + c.amount, 0);\n const taxExclusiveAmount = round2(lineExtensionAmount - allowanceTotalAmount + chargeTotalAmount);\n const totalTax = round2(taxSubtotals.reduce((sum, st) => sum + st.taxAmount, 0));\n const taxInclusiveAmount = round2(taxExclusiveAmount + totalTax);\n return {\n lineExtensionAmount,\n allowanceTotalAmount,\n chargeTotalAmount,\n taxExclusiveAmount,\n totalTax,\n taxInclusiveAmount,\n payableAmount: taxInclusiveAmount,\n taxSubtotals,\n };\n}\n\nfunction buildTaxTotalXml(taxSubtotals: TaxSubtotal[], totalTax: number, currency: string): string {\n const subtotalsXml = taxSubtotals\n .map(\n (st) => `\n <cac:TaxSubtotal>\n <cbc:TaxableAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(st.taxableAmount)}</cbc:TaxableAmount>\n <cbc:TaxAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(st.taxAmount)}</cbc:TaxAmount>\n <cac:TaxCategory>\n <cbc:ID>${st.vatCategory}</cbc:ID>\n <cbc:Percent>${st.vatRate}</cbc:Percent>\n <cac:TaxScheme>\n <cbc:ID>VAT</cbc:ID>\n </cac:TaxScheme>\n </cac:TaxCategory>\n </cac:TaxSubtotal>`,\n )\n .join(\"\");\n\n return `<cac:TaxTotal>\n <cbc:TaxAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totalTax)}</cbc:TaxAmount>\n ${subtotalsXml}\n </cac:TaxTotal>`;\n}\n\nfunction buildTaxCurrencyTotalXml(totalTax: number, taxCurrency: string, rate: number): string {\n const convertedAmount = Math.round(totalTax * rate * 100) / 100;\n return `<cac:TaxTotal>\n <cbc:TaxAmount currencyID=\"${escapeXml(taxCurrency)}\">${formatAmount(convertedAmount)}</cbc:TaxAmount>\n </cac:TaxTotal>`;\n}\n\ninterface LegalMonetaryTotalOptions {\n prepaidAmount?: number;\n roundingAmount?: number;\n}\n\nfunction buildLegalMonetaryTotalXml(totals: DocumentTotals, currency: string, options?: LegalMonetaryTotalOptions): string {\n const prepaid = options?.prepaidAmount;\n const rounding = options?.roundingAmount;\n const payableAmount = totals.taxInclusiveAmount - (prepaid ?? 0) + (rounding ?? 0);\n\n return `<cac:LegalMonetaryTotal>\n <cbc:LineExtensionAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.lineExtensionAmount)}</cbc:LineExtensionAmount>\n <cbc:TaxExclusiveAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.taxExclusiveAmount)}</cbc:TaxExclusiveAmount>\n <cbc:TaxInclusiveAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.taxInclusiveAmount)}</cbc:TaxInclusiveAmount>\n ${totals.allowanceTotalAmount > 0 ? `<cbc:AllowanceTotalAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.allowanceTotalAmount)}</cbc:AllowanceTotalAmount>` : \"\"}\n ${totals.chargeTotalAmount > 0 ? `<cbc:ChargeTotalAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(totals.chargeTotalAmount)}</cbc:ChargeTotalAmount>` : \"\"}\n ${prepaid != null ? `<cbc:PrepaidAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(prepaid)}</cbc:PrepaidAmount>` : \"\"}\n ${rounding != null ? `<cbc:PayableRoundingAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(rounding)}</cbc:PayableRoundingAmount>` : \"\"}\n <cbc:PayableAmount currencyID=\"${escapeXml(currency)}\">${formatAmount(payableAmount)}</cbc:PayableAmount>\n </cac:LegalMonetaryTotal>`;\n}\n\nfunction buildPaymentMeansXml(input: InvoiceInput | CreditNoteInput): string {\n const paymentMeans = input.paymentMeans ?? DEFAULT_PAYMENT_MEANS;\n return `<cac:PaymentMeans>\n <cbc:PaymentMeansCode>${paymentMeans}</cbc:PaymentMeansCode>\n ${input.paymentReference ? `<cbc:PaymentID>${escapeXml(input.paymentReference)}</cbc:PaymentID>` : \"\"}\n ${\n input.paymentIban\n ? `<cac:PayeeFinancialAccount>\n <cbc:ID>${escapeXml(input.paymentIban)}</cbc:ID>\n ${\n input.paymentBic\n ? `<cac:FinancialInstitutionBranch>\n <cbc:ID>${escapeXml(input.paymentBic)}</cbc:ID>\n </cac:FinancialInstitutionBranch>`\n : \"\"\n }\n </cac:PayeeFinancialAccount>`\n : \"\"\n }\n </cac:PaymentMeans>`;\n}\n\nfunction buildCreditNoteLineXml(line: InvoiceLine, index: number, currency: string): string {\n return buildDocumentLineXml(line, index, currency, \"CreditNoteLine\", \"CreditedQuantity\");\n}\n\nfunction buildOrderReferenceXml(orderReference?: string, salesOrderReference?: string): string {\n if (!orderReference && !salesOrderReference) return \"\";\n const parts: string[] = [\"<cac:OrderReference>\"];\n if (orderReference) {\n parts.push(`<cbc:ID>${escapeXml(orderReference)}</cbc:ID>`);\n }\n if (salesOrderReference) {\n parts.push(`<cbc:SalesOrderID>${escapeXml(salesOrderReference)}</cbc:SalesOrderID>`);\n }\n parts.push(\"</cac:OrderReference>\");\n return parts.join(\"\");\n}\n\n/**\n * Build a Peppol BIS 3.0 compliant UBL 2.1 Invoice XML from a simple JSON input.\n */\nexport function buildInvoiceXml(input: InvoiceInput): string {\n const currency = input.currency ?? \"EUR\";\n const date = formatDate(input.date);\n const dueDate = input.dueDate ? formatDate(input.dueDate) : undefined;\n const hasTaxCurrency = input.taxCurrency && input.taxCurrency !== currency;\n const totals = calculateDocumentTotals(input.lines, input.allowances, input.charges);\n\n const linesXml = input.lines\n .map((line, i) => buildInvoiceLineXml(line, i, currency))\n .join(\"\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Invoice xmlns=\"${UBL_NS}\"\n xmlns:cac=\"${CAC_NS}\"\n xmlns:cbc=\"${CBC_NS}\">\n <cbc:CustomizationID>${PEPPOL_CUSTOMIZATION_ID}</cbc:CustomizationID>\n <cbc:ProfileID>${PEPPOL_PROFILE_ID}</cbc:ProfileID>\n <cbc:ID>${escapeXml(input.number)}</cbc:ID>\n <cbc:IssueDate>${date}</cbc:IssueDate>\n ${dueDate ? `<cbc:DueDate>${dueDate}</cbc:DueDate>` : \"\"}\n ${input.taxPointDate ? `<cbc:TaxPointDate>${formatDate(input.taxPointDate)}</cbc:TaxPointDate>` : \"\"}\n <cbc:InvoiceTypeCode>${input.invoiceTypeCode ?? (input.isCreditNote ? 381 : 380)}</cbc:InvoiceTypeCode>\n ${input.note ? `<cbc:Note>${escapeXml(input.note)}</cbc:Note>` : \"\"}\n ${input.accountingCost ? `<cbc:AccountingCost>${escapeXml(input.accountingCost)}</cbc:AccountingCost>` : \"\"}\n <cbc:DocumentCurrencyCode>${escapeXml(currency)}</cbc:DocumentCurrencyCode>\n ${hasTaxCurrency ? `<cbc:TaxCurrencyCode>${escapeXml(input.taxCurrency!)}</cbc:TaxCurrencyCode>` : \"\"}\n ${input.buyerReference ? `<cbc:BuyerReference>${escapeXml(input.buyerReference)}</cbc:BuyerReference>` : \"\"}\n ${input.invoicePeriod ? buildInvoicePeriodXml(input.invoicePeriod) : \"\"}\n ${buildOrderReferenceXml(input.orderReference, input.salesOrderReference)}\n ${input.despatchReference ? `<cac:DespatchDocumentReference><cbc:ID>${escapeXml(input.despatchReference)}</cbc:ID></cac:DespatchDocumentReference>` : \"\"}\n ${input.receiptReference ? `<cac:ReceiptDocumentReference><cbc:ID>${escapeXml(input.receiptReference)}</cbc:ID></cac:ReceiptDocumentReference>` : \"\"}\n ${input.contractReference ? `<cac:ContractDocumentReference><cbc:ID>${escapeXml(input.contractReference)}</cbc:ID></cac:ContractDocumentReference>` : \"\"}\n ${(input.attachments ?? []).map((a) => buildAttachmentXml(a)).join(\"\\n \")}\n ${input.projectReference ? `<cac:ProjectReference><cbc:ID>${escapeXml(input.projectReference)}</cbc:ID></cac:ProjectReference>` : \"\"}\n ${input.from ? buildPartyXml(input.from, \"AccountingSupplierParty\") : \"\"}\n ${buildPartyXml(input.to, \"AccountingCustomerParty\")}\n ${input.payeeParty ? buildPayeePartyXml(input.payeeParty) : \"\"}\n ${input.taxRepresentative ? buildTaxRepresentativePartyXml(input.taxRepresentative) : \"\"}\n ${input.delivery ? buildDeliveryXml(input.delivery) : \"\"}\n ${buildPaymentMeansXml(input)}\n ${input.paymentTerms ? `<cac:PaymentTerms>\\n <cbc:Note>${escapeXml(input.paymentTerms)}</cbc:Note>\\n </cac:PaymentTerms>` : \"\"}\n ${(input.allowances ?? []).map((a) => buildDocumentAllowanceChargeXml(a, false, currency)).join(\"\")}\n ${(input.charges ?? []).map((c) => buildDocumentAllowanceChargeXml(c, true, currency)).join(\"\")}\n ${hasTaxCurrency && input.taxCurrencyRate ? buildTaxCurrencyTotalXml(totals.totalTax, input.taxCurrency!, input.taxCurrencyRate) : \"\"}\n ${buildTaxTotalXml(totals.taxSubtotals, totals.totalTax, currency)}\n ${buildLegalMonetaryTotalXml(totals, currency, { prepaidAmount: input.prepaidAmount, roundingAmount: input.roundingAmount })}\n ${linesXml}\n</Invoice>`;\n}\n\n/**\n * Build a Peppol BIS 3.0 compliant UBL 2.1 Credit Note XML.\n *\n * Generates XML directly with correct CreditNote elements — no string replacement.\n */\nexport function buildCreditNoteXml(input: CreditNoteInput): string {\n const currency = input.currency ?? \"EUR\";\n const date = formatDate(input.date);\n const dueDate = input.dueDate ? formatDate(input.dueDate) : undefined;\n const hasTaxCurrency = input.taxCurrency && input.taxCurrency !== currency;\n const totals = calculateDocumentTotals(input.lines, input.allowances, input.charges);\n\n const linesXml = input.lines\n .map((line, i) => buildCreditNoteLineXml(line, i, currency))\n .join(\"\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreditNote xmlns=\"${CREDIT_NOTE_NS}\"\n xmlns:cac=\"${CAC_NS}\"\n xmlns:cbc=\"${CBC_NS}\">\n <cbc:CustomizationID>${PEPPOL_CUSTOMIZATION_ID}</cbc:CustomizationID>\n <cbc:ProfileID>${PEPPOL_PROFILE_ID}</cbc:ProfileID>\n <cbc:ID>${escapeXml(input.number)}</cbc:ID>\n <cbc:IssueDate>${date}</cbc:IssueDate>\n ${dueDate ? `<cbc:DueDate>${dueDate}</cbc:DueDate>` : \"\"}\n ${input.taxPointDate ? `<cbc:TaxPointDate>${formatDate(input.taxPointDate)}</cbc:TaxPointDate>` : \"\"}\n <cbc:CreditNoteTypeCode>${input.invoiceTypeCode ?? 381}</cbc:CreditNoteTypeCode>\n ${input.note ? `<cbc:Note>${escapeXml(input.note)}</cbc:Note>` : \"\"}\n ${input.accountingCost ? `<cbc:AccountingCost>${escapeXml(input.accountingCost)}</cbc:AccountingCost>` : \"\"}\n <cbc:DocumentCurrencyCode>${escapeXml(currency)}</cbc:DocumentCurrencyCode>\n ${hasTaxCurrency ? `<cbc:TaxCurrencyCode>${escapeXml(input.taxCurrency!)}</cbc:TaxCurrencyCode>` : \"\"}\n ${input.buyerReference ? `<cbc:BuyerReference>${escapeXml(input.buyerReference)}</cbc:BuyerReference>` : \"\"}\n ${input.invoicePeriod ? buildInvoicePeriodXml(input.invoicePeriod) : \"\"}\n ${buildOrderReferenceXml(input.orderReference, input.salesOrderReference)}\n <cac:BillingReference><cac:InvoiceDocumentReference><cbc:ID>${escapeXml(input.invoiceReference)}</cbc:ID></cac:InvoiceDocumentReference></cac:BillingReference>\n ${input.despatchReference ? `<cac:DespatchDocumentReference><cbc:ID>${escapeXml(input.despatchReference)}</cbc:ID></cac:DespatchDocumentReference>` : \"\"}\n ${input.receiptReference ? `<cac:ReceiptDocumentReference><cbc:ID>${escapeXml(input.receiptReference)}</cbc:ID></cac:ReceiptDocumentReference>` : \"\"}\n ${input.contractReference ? `<cac:ContractDocumentReference><cbc:ID>${escapeXml(input.contractReference)}</cbc:ID></cac:ContractDocumentReference>` : \"\"}\n ${(input.attachments ?? []).map((a) => buildAttachmentXml(a)).join(\"\\n \")}\n ${input.projectReference ? `<cac:ProjectReference><cbc:ID>${escapeXml(input.projectReference)}</cbc:ID></cac:ProjectReference>` : \"\"}\n ${input.from ? buildPartyXml(input.from, \"AccountingSupplierParty\") : \"\"}\n ${buildPartyXml(input.to, \"AccountingCustomerParty\")}\n ${input.payeeParty ? buildPayeePartyXml(input.payeeParty) : \"\"}\n ${input.taxRepresentative ? buildTaxRepresentativePartyXml(input.taxRepresentative) : \"\"}\n ${input.delivery ? buildDeliveryXml(input.delivery) : \"\"}\n ${buildPaymentMeansXml(input)}\n ${input.paymentTerms ? `<cac:PaymentTerms>\\n <cbc:Note>${escapeXml(input.paymentTerms)}</cbc:Note>\\n </cac:PaymentTerms>` : \"\"}\n ${(input.allowances ?? []).map((a) => buildDocumentAllowanceChargeXml(a, false, currency)).join(\"\")}\n ${(input.charges ?? []).map((c) => buildDocumentAllowanceChargeXml(c, true, currency)).join(\"\")}\n ${hasTaxCurrency && input.taxCurrencyRate ? buildTaxCurrencyTotalXml(totals.totalTax, input.taxCurrency!, input.taxCurrencyRate) : \"\"}\n ${buildTaxTotalXml(totals.taxSubtotals, totals.totalTax, currency)}\n ${buildLegalMonetaryTotalXml(totals, currency, { prepaidAmount: input.prepaidAmount, roundingAmount: input.roundingAmount })}\n ${linesXml}\n</CreditNote>`;\n}\n","/**\n * Country-Specific Validation Rules\n *\n * Produces warnings (not blocking errors) for country-specific invoice requirements.\n * Invoices can still be sent, but developers get helpful feedback about\n * local compliance expectations.\n *\n * Each rule has a unique ID: {CC}-{NN} (e.g., BE-01, FR-02).\n */\n\nimport type {\n InvoiceInput,\n ValidationError,\n ValidationWarning,\n} from \"../types/invoice.js\";\n\n// ─── Result Type ─────────────────────────────────────────────\n\nexport interface CountryValidationResult {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────\n\nfunction warn(field: string, message: string, ruleId: string): ValidationWarning {\n return { field, message, ruleId };\n}\n\n// ─── Belgium (BE) ────────────────────────────────────────────\n\n/**\n * Belgian structured communication format: +++NNN/NNNN/NNNNN+++\n * The last 2 of the 12 digits are a mod-97 check digit.\n * If base mod 97 === 0, the check digit is 97.\n */\nconst BE_STRUCTURED_RE = /^\\+{3}\\d{3}\\/\\d{4}\\/\\d{5}\\+{3}$/;\n\nfunction validateBelgianCheckDigit(reference: string): boolean {\n // Extract the 12 digits from +++NNN/NNNN/NNNNN+++\n const digits = reference.replace(/[^0-9]/g, \"\");\n if (digits.length !== 12) return false;\n\n const base = parseInt(digits.slice(0, 10), 10);\n const check = parseInt(digits.slice(10, 12), 10);\n const expected = base % 97 === 0 ? 97 : base % 97;\n\n return check === expected;\n}\n\nfunction validateBelgium(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const ref = input.paymentReference;\n\n if (ref && BE_STRUCTURED_RE.test(ref)) {\n // It's in structured format — verify the checksum\n if (!validateBelgianCheckDigit(ref)) {\n warnings.push(\n warn(\n \"paymentReference\",\n `Belgian structured communication \"${ref}\" has an invalid mod-97 checksum. Verify the reference.`,\n \"BE-01\",\n ),\n );\n }\n } else if (!ref) {\n warnings.push(\n warn(\n \"paymentReference\",\n \"Belgian recipients typically expect a structured communication reference (+++NNN/NNNN/NNNNN+++ format).\",\n \"BE-02\",\n ),\n );\n }\n}\n\n/**\n * Seller-direction Belgian rules: only payment reference validation.\n * Separated from validateBelgium() to prevent buyer-focused rules\n * from accidentally firing with buyer data in a seller context.\n */\nfunction validateBelgiumSeller(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const ref = input.paymentReference;\n\n if (ref && BE_STRUCTURED_RE.test(ref)) {\n if (!validateBelgianCheckDigit(ref)) {\n warnings.push(\n warn(\n \"paymentReference\",\n `Belgian structured communication \"${ref}\" has an invalid mod-97 checksum. Verify the reference.`,\n \"BE-01\",\n ),\n );\n }\n } else if (!ref) {\n warnings.push(\n warn(\n \"paymentReference\",\n \"Belgian sellers typically include a structured communication reference (+++NNN/NNNN/NNNNN+++ format).\",\n \"BE-02\",\n ),\n );\n }\n}\n\n// ─── France (FR) ─────────────────────────────────────────────\n\nconst FR_SIRET_RE = /^\\d{14}$/;\nconst FR_VAT_RE = /^FR[A-Z0-9]{2}\\d{9}$/;\n\nfunction validateFrance(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const { companyId, vatNumber } = input.to ?? {};\n\n if (companyId && !FR_SIRET_RE.test(companyId)) {\n warnings.push(\n warn(\n \"to.companyId\",\n `French company ID (SIRET) should be exactly 14 digits, got \"${companyId}\".`,\n \"FR-01\",\n ),\n );\n }\n\n if (vatNumber && !FR_VAT_RE.test(vatNumber)) {\n warnings.push(\n warn(\n \"to.vatNumber\",\n `French VAT number should match format FR + 2 characters + 9 digits (SIREN), got \"${vatNumber}\".`,\n \"FR-02\",\n ),\n );\n }\n}\n\n// ─── Italy (IT) ──────────────────────────────────────────────\n\nfunction validateItaly(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n if (!input.buyerReference) {\n warnings.push(\n warn(\n \"buyerReference\",\n \"Italian recipients (SDI) typically require a buyer reference (CIG/CUP code). Consider setting buyerReference.\",\n \"IT-01\",\n ),\n );\n }\n\n const peppolId = input.to?.peppolId;\n if (peppolId?.startsWith(\"0201:\")) {\n const fiscalCode = peppolId.slice(5);\n if (fiscalCode.length !== 11 && fiscalCode.length !== 16) {\n warnings.push(\n warn(\n \"to.peppolId\",\n `Italian fiscal code (after 0201:) should be 11 digits (partita IVA) or 16 characters (codice fiscale), got ${fiscalCode.length} characters.`,\n \"IT-02\",\n ),\n );\n }\n }\n}\n\n// ─── Netherlands (NL) ───────────────────────────────────────\n\nconst NL_KVK_RE = /^\\d{8}$/;\nconst NL_VAT_RE = /^NL\\d{9}B\\d{2}$/;\n\nfunction validateNetherlands(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const { companyId, vatNumber } = input.to ?? {};\n\n if (companyId && !NL_KVK_RE.test(companyId)) {\n warnings.push(\n warn(\n \"to.companyId\",\n `Dutch KVK number should be exactly 8 digits, got \"${companyId}\".`,\n \"NL-01\",\n ),\n );\n }\n\n if (vatNumber && !NL_VAT_RE.test(vatNumber)) {\n warnings.push(\n warn(\n \"to.vatNumber\",\n `Dutch VAT number should match format NL + 9 digits + B + 2 digits, got \"${vatNumber}\".`,\n \"NL-02\",\n ),\n );\n }\n}\n\n// ─── Germany (DE) ────────────────────────────────────────────\n\nconst DE_VAT_RE = /^DE\\d{9}$/;\n\nfunction validateGermany(\n input: InvoiceInput,\n _errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n const { vatNumber } = input.to ?? {};\n\n if (vatNumber && !DE_VAT_RE.test(vatNumber)) {\n warnings.push(\n warn(\n \"to.vatNumber\",\n `German VAT number should match format DE + 9 digits, got \"${vatNumber}\".`,\n \"DE-01\",\n ),\n );\n }\n}\n\n// ─── Main Entry Point ───────────────────────────────────────\n\n/**\n * Validate country-specific rules for an invoice.\n *\n * Returns warnings for common compliance issues specific to the\n * recipient's country. These are advisory — the invoice can still be sent.\n *\n * @example\n * ```ts\n * const result = validateCountryRules(invoice);\n * for (const w of result.warnings) {\n * console.warn(`[${w.ruleId}] ${w.field}: ${w.message}`);\n * }\n * ```\n */\nexport function validateCountryRules(input: InvoiceInput): CountryValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n const buyerCountry = input.to?.country;\n const sellerCountry = input.from?.country;\n\n // Buyer-country rules\n if (buyerCountry) {\n switch (buyerCountry) {\n case \"BE\": validateBelgium(input, errors, warnings); break;\n case \"FR\": validateFrance(input, errors, warnings); break;\n case \"IT\": validateItaly(input, errors, warnings); break;\n case \"NL\": validateNetherlands(input, errors, warnings); break;\n case \"DE\": validateGermany(input, errors, warnings); break;\n }\n }\n\n // Seller-country rules (skip if same as buyer to avoid duplicates)\n if (sellerCountry && sellerCountry !== buyerCountry) {\n switch (sellerCountry) {\n case \"BE\": validateBelgiumSeller(input, errors, warnings); break;\n }\n }\n\n return { errors, warnings };\n}\n","/**\n * Peppol Code Lists — Static lookup utilities\n *\n * Provides tree-shakeable helper functions for common Peppol-related code lists:\n * countries, EAS schemes, unit codes, VAT categories, and payment means.\n *\n * All data is static — no API calls, no side effects.\n */\n\n// ─── Countries (ISO 3166-1 alpha-2) ───────────────────────────────────────────\n\n/** EU + EEA + common Peppol trading partners (~50 most used) */\nconst COUNTRIES: ReadonlyMap<string, string> = new Map([\n // EU member states\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 [\"IE\", \"Ireland\"],\n [\"IT\", \"Italy\"],\n [\"LV\", \"Latvia\"],\n [\"LT\", \"Lithuania\"],\n [\"LU\", \"Luxembourg\"],\n [\"MT\", \"Malta\"],\n [\"NL\", \"Netherlands\"],\n [\"PL\", \"Poland\"],\n [\"PT\", \"Portugal\"],\n [\"RO\", \"Romania\"],\n [\"SK\", \"Slovakia\"],\n [\"SI\", \"Slovenia\"],\n [\"ES\", \"Spain\"],\n [\"SE\", \"Sweden\"],\n // EEA (non-EU)\n [\"IS\", \"Iceland\"],\n [\"LI\", \"Liechtenstein\"],\n [\"NO\", \"Norway\"],\n // Common Peppol trading partners\n [\"GB\", \"United Kingdom\"],\n [\"CH\", \"Switzerland\"],\n [\"US\", \"United States\"],\n [\"CA\", \"Canada\"],\n [\"AU\", \"Australia\"],\n [\"NZ\", \"New Zealand\"],\n [\"SG\", \"Singapore\"],\n [\"JP\", \"Japan\"],\n [\"KR\", \"South Korea\"],\n [\"IN\", \"India\"],\n [\"TR\", \"Turkey\"],\n [\"SA\", \"Saudi Arabia\"],\n [\"AE\", \"United Arab Emirates\"],\n [\"IL\", \"Israel\"],\n [\"ZA\", \"South Africa\"],\n [\"BR\", \"Brazil\"],\n [\"MX\", \"Mexico\"],\n [\"MY\", \"Malaysia\"],\n [\"TH\", \"Thailand\"],\n [\"ID\", \"Indonesia\"],\n]);\n\n/**\n * Get the country name for an ISO 3166-1 alpha-2 code.\n *\n * @param code - Two-letter country code (case-insensitive)\n * @returns Country name or `undefined` if not found\n *\n * @example\n * ```ts\n * getCountryName(\"FR\") // \"France\"\n * getCountryName(\"XX\") // undefined\n * ```\n */\nexport function getCountryName(code: string): string | undefined {\n return COUNTRIES.get(code.toUpperCase());\n}\n\n/**\n * Get all supported countries.\n *\n * @returns Array of `{ code, name }` objects sorted by name\n */\nexport function getAllCountries(): Array<{ code: string; name: string }> {\n return Array.from(COUNTRIES.entries())\n .map(([code, name]) => ({ code, name }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n// ─── Currencies (ISO 4217) ────────────────────────────────────────────────────\n\n/**\n * A currency entry per ISO 4217.\n */\nexport interface Currency {\n /** Three-letter ISO 4217 code (uppercase) */\n code: string;\n /** Currency name */\n name: string;\n /** Standard minor unit count (e.g., 2 for EUR, 0 for JPY, 3 for BHD) */\n minorUnits: number;\n}\n\n/** Common Peppol/EU trade currencies (~30 most used) */\nconst CURRENCIES: ReadonlyMap<string, Currency> = new Map([\n [\"EUR\", { code: \"EUR\", name: \"Euro\", minorUnits: 2 }],\n [\"USD\", { code: \"USD\", name: \"US Dollar\", minorUnits: 2 }],\n [\"GBP\", { code: \"GBP\", name: \"Pound Sterling\", minorUnits: 2 }],\n [\"CHF\", { code: \"CHF\", name: \"Swiss Franc\", minorUnits: 2 }],\n [\"DKK\", { code: \"DKK\", name: \"Danish Krone\", minorUnits: 2 }],\n [\"NOK\", { code: \"NOK\", name: \"Norwegian Krone\", minorUnits: 2 }],\n [\"SEK\", { code: \"SEK\", name: \"Swedish Krona\", minorUnits: 2 }],\n [\"PLN\", { code: \"PLN\", name: \"Polish Zloty\", minorUnits: 2 }],\n [\"CZK\", { code: \"CZK\", name: \"Czech Koruna\", minorUnits: 2 }],\n [\"HUF\", { code: \"HUF\", name: \"Hungarian Forint\", minorUnits: 2 }],\n [\"RON\", { code: \"RON\", name: \"Romanian Leu\", minorUnits: 2 }],\n [\"BGN\", { code: \"BGN\", name: \"Bulgarian Lev\", minorUnits: 2 }],\n [\"HRK\", { code: \"HRK\", name: \"Croatian Kuna\", minorUnits: 2 }],\n [\"ISK\", { code: \"ISK\", name: \"Icelandic Krona\", minorUnits: 0 }],\n [\"TRY\", { code: \"TRY\", name: \"Turkish Lira\", minorUnits: 2 }],\n [\"JPY\", { code: \"JPY\", name: \"Japanese Yen\", minorUnits: 0 }],\n [\"CNY\", { code: \"CNY\", name: \"Chinese Yuan\", minorUnits: 2 }],\n [\"KRW\", { code: \"KRW\", name: \"South Korean Won\", minorUnits: 0 }],\n [\"INR\", { code: \"INR\", name: \"Indian Rupee\", minorUnits: 2 }],\n [\"SGD\", { code: \"SGD\", name: \"Singapore Dollar\", minorUnits: 2 }],\n [\"AUD\", { code: \"AUD\", name: \"Australian Dollar\", minorUnits: 2 }],\n [\"NZD\", { code: \"NZD\", name: \"New Zealand Dollar\", minorUnits: 2 }],\n [\"CAD\", { code: \"CAD\", name: \"Canadian Dollar\", minorUnits: 2 }],\n [\"BRL\", { code: \"BRL\", name: \"Brazilian Real\", minorUnits: 2 }],\n [\"MXN\", { code: \"MXN\", name: \"Mexican Peso\", minorUnits: 2 }],\n [\"ZAR\", { code: \"ZAR\", name: \"South African Rand\", minorUnits: 2 }],\n [\"AED\", { code: \"AED\", name: \"UAE Dirham\", minorUnits: 2 }],\n [\"SAR\", { code: \"SAR\", name: \"Saudi Riyal\", minorUnits: 2 }],\n [\"ILS\", { code: \"ILS\", name: \"Israeli Shekel\", minorUnits: 2 }],\n [\"HKD\", { code: \"HKD\", name: \"Hong Kong Dollar\", minorUnits: 2 }],\n [\"TWD\", { code: \"TWD\", name: \"Taiwan Dollar\", minorUnits: 2 }],\n]);\n\n/**\n * Look up a currency by ISO 4217 code.\n *\n * @param code - Three-letter currency code (case-insensitive)\n * @returns The currency entry or `undefined` if not found\n *\n * @example\n * ```ts\n * getCurrency(\"EUR\") // { code: \"EUR\", name: \"Euro\", minorUnits: 2 }\n * getCurrency(\"eu\") // undefined\n * ```\n */\nexport function getCurrency(code: string): Currency | undefined {\n return CURRENCIES.get(code.toUpperCase());\n}\n\n/**\n * Get all supported currencies.\n *\n * @returns Array sorted by ISO code ascending\n */\nexport function getAllCurrencies(): Currency[] {\n return Array.from(CURRENCIES.values()).sort((a, b) => a.code.localeCompare(b.code));\n}\n\n// ─── EAS Schemes (Peppol participant identifier schemes) ──────────────────────\n\n/**\n * A Peppol Electronic Address Scheme (EAS) entry.\n */\nexport interface EasScheme {\n /** Numeric EAS code (e.g. \"0088\") */\n code: string;\n /** Human-readable scheme name */\n name: string;\n /** ISO country code if scheme is country-specific */\n country?: string;\n}\n\nconst EAS_SCHEMES: readonly EasScheme[] = [\n { code: \"0002\", name: \"System Information et Repertoire des Entreprises et des Etablissements (SIRENE)\", country: \"FR\" },\n { code: \"0007\", name: \"Organisationsnummer\", country: \"SE\" },\n { code: \"0009\", name: \"SIRET-CODE\", country: \"FR\" },\n { code: \"0088\", name: \"EAN Location Code (GLN)\" },\n { code: \"0096\", name: \"Danish Chamber of Commerce (P-nummer)\", country: \"DK\" },\n { code: \"0184\", name: \"Danish Central Business Register (CVR)\", country: \"DK\" },\n { code: \"0190\", name: \"Dutch Chamber of Commerce (KVK)\", country: \"NL\" },\n { code: \"0191\", name: \"Organisatie Identificatie Nummer (OIN)\", country: \"NL\" },\n { code: \"0192\", name: \"Danish SE-number (Erhvervsstyrelsen)\", country: \"DK\" },\n { code: \"0195\", name: \"Singapore Unique Entity Number (UEN)\", country: \"SG\" },\n { code: \"0196\", name: \"Icelandic Kennitala\", country: \"IS\" },\n { code: \"0198\", name: \"Danish ERST id (Erhvervsstyrelsen)\", country: \"DK\" },\n { code: \"0200\", name: \"Lithuanian Legal Entity Register (GRIS)\", country: \"LT\" },\n { code: \"0201\", name: \"Italian Codice Destinatario\", country: \"IT\" },\n { code: \"0202\", name: \"Italian Fiscal Code (Codice Fiscale)\", country: \"IT\" },\n { code: \"0204\", name: \"German Leitweg-ID\", country: \"DE\" },\n { code: \"0208\", name: \"Belgian Enterprise Number (KBO/BCE)\", country: \"BE\" },\n { code: \"0209\", name: \"German Creditor Identifier (GS1)\", country: \"DE\" },\n { code: \"0210\", name: \"Italian Codice Fiscale (per IPA)\", country: \"IT\" },\n { code: \"0211\", name: \"Italian Partita IVA (VAT number)\", country: \"IT\" },\n { code: \"0212\", name: \"Finnish OVT code\", country: \"FI\" },\n { code: \"0213\", name: \"Finnish OP identifier\", country: \"FI\" },\n { code: \"0225\", name: \"FRCTC Electronic Address\", country: \"FR\" },\n { code: \"9957\", name: \"French VAT number\", country: \"FR\" },\n] as const;\n\n/** Lookup index: EAS code → scheme */\nconst EAS_BY_CODE: ReadonlyMap<string, EasScheme> = new Map(\n EAS_SCHEMES.map((s) => [s.code, s]),\n);\n\n/**\n * Look up an EAS scheme by its numeric code.\n *\n * @param code - EAS code (e.g. \"0088\", \"0208\")\n * @returns The scheme or `undefined` if not found\n *\n * @example\n * ```ts\n * getEasScheme(\"0208\") // { code: \"0208\", name: \"Belgian Enterprise Number (KBO/BCE)\", country: \"BE\" }\n * getEasScheme(\"9999\") // undefined\n * ```\n */\nexport function getEasScheme(code: string): EasScheme | undefined {\n return EAS_BY_CODE.get(code);\n}\n\n/**\n * Get all known EAS schemes.\n *\n * @returns Array of EAS schemes sorted by code\n */\nexport function getAllEasSchemes(): EasScheme[] {\n return [...EAS_SCHEMES];\n}\n\n// ─── Unit Codes (UN/ECE Recommendation 20) ────────────────────────────────────\n\n/** Human-readable aliases → UN/ECE unit codes */\nconst UNIT_ALIAS_MAP: Record<string, string> = {\n each: \"EA\", piece: \"EA\", pieces: \"EA\",\n hour: \"HUR\", hours: \"HUR\",\n day: \"DAY\", days: \"DAY\",\n week: \"WEE\", weeks: \"WEE\",\n month: \"MON\", months: \"MON\",\n year: \"ANN\", years: \"ANN\",\n kilogram: \"KGM\", kg: \"KGM\",\n meter: \"MTR\", metre: \"MTR\",\n liter: \"LTR\", litre: \"LTR\",\n unit: \"C62\", units: \"C62\",\n set: \"SET\", sets: \"SET\",\n pack: \"PK\", packs: \"PK\",\n minute: \"MIN\", minutes: \"MIN\",\n second: \"SEC\", seconds: \"SEC\",\n tonne: \"TNE\", ton: \"TNE\",\n \"square metre\": \"MTK\", \"square meter\": \"MTK\", sqm: \"MTK\",\n};\n\n/** Canonical unit codes with human-readable names */\nconst UNIT_CODES: ReadonlyMap<string, string> = new Map([\n [\"EA\", \"Each\"],\n [\"HUR\", \"Hour\"],\n [\"DAY\", \"Day\"],\n [\"WEE\", \"Week\"],\n [\"MON\", \"Month\"],\n [\"ANN\", \"Year\"],\n [\"MIN\", \"Minute\"],\n [\"SEC\", \"Second\"],\n [\"KGM\", \"Kilogram\"],\n [\"MTR\", \"Metre\"],\n [\"LTR\", \"Litre\"],\n [\"MTK\", \"Square metre\"],\n [\"TNE\", \"Tonne\"],\n [\"C62\", \"One (unit)\"],\n [\"SET\", \"Set\"],\n [\"PK\", \"Pack\"],\n]);\n\n/**\n * Resolve a human-readable unit name or alias to its UN/ECE Recommendation 20 code.\n *\n * Accepts both aliases (\"hours\", \"kg\") and canonical codes (\"HUR\", \"KGM\").\n * Unknown values pass through unchanged.\n *\n * @param input - Unit name or code\n * @returns Resolved UN/ECE code\n *\n * @example\n * ```ts\n * resolveUnit(\"hours\") // \"HUR\"\n * resolveUnit(\"HUR\") // \"HUR\"\n * resolveUnit(\"kg\") // \"KGM\"\n * resolveUnit(\"XYZ\") // \"XYZ\" (passthrough)\n * ```\n */\nexport function resolveUnit(input: string): string {\n return UNIT_ALIAS_MAP[input.toLowerCase()] ?? input;\n}\n\n/**\n * Get all supported unit codes with human-readable names.\n *\n * @returns Array of `{ code, name }` objects sorted by code\n */\nexport function getAllUnits(): Array<{ code: string; name: string }> {\n return Array.from(UNIT_CODES.entries())\n .map(([code, name]) => ({ code, name }))\n .sort((a, b) => a.code.localeCompare(b.code));\n}\n\n// ─── VAT Categories (UNCL 5305) ──────────────────────────────────────────────\n\n/**\n * A Peppol VAT category entry.\n */\nexport interface VatCategory {\n /** Category code (e.g. \"S\", \"Z\", \"AE\") */\n code: string;\n /** Short name */\n name: string;\n /** Longer description */\n description: string;\n}\n\nconst VAT_CATEGORIES: readonly VatCategory[] = [\n { code: \"S\", name: \"Standard rate\", description: \"Standard VAT rate applies\" },\n { code: \"Z\", name: \"Zero rated\", description: \"Zero-rated goods — VAT at 0% but right to deduct input VAT\" },\n { code: \"E\", name: \"Exempt\", description: \"Exempt from VAT — no right to deduct input VAT\" },\n { code: \"AE\", name: \"Reverse charge\", description: \"VAT reverse charge — customer accounts for VAT\" },\n { code: \"K\", name: \"Intra-community supply\", description: \"Intra-community supply of goods — exempt with right to deduct\" },\n { code: \"G\", name: \"Export outside the EU\", description: \"Free export item — tax not charged\" },\n { code: \"O\", name: \"Outside scope of VAT\", description: \"Services outside scope of VAT\" },\n { code: \"L\", name: \"Canary Islands IGIC\", description: \"Canary Islands general indirect tax (IGIC)\" },\n { code: \"M\", name: \"Ceuta and Melilla IPSI\", description: \"Tax for production, services and importation in Ceuta and Melilla (IPSI)\" },\n] as const;\n\n/**\n * Get all Peppol VAT category codes.\n *\n * @returns Array of VAT categories\n */\nexport function getVatCategories(): VatCategory[] {\n return [...VAT_CATEGORIES];\n}\n\n// ─── Payment Means (UNCL 4461) ───────────────────────────────────────────────\n\n/**\n * A payment means code entry.\n */\nexport interface PaymentMeansCode {\n /** Numeric code */\n code: number;\n /** Human-readable description */\n name: string;\n}\n\nconst PAYMENT_MEANS_CODES: readonly PaymentMeansCode[] = [\n { code: 10, name: \"Cash\" },\n { code: 20, name: \"Cheque\" },\n { code: 30, name: \"Credit transfer\" },\n { code: 42, name: \"Payment to bank account\" },\n { code: 48, name: \"Bank card\" },\n { code: 49, name: \"Direct debit\" },\n { code: 57, name: \"Standing agreement\" },\n { code: 58, name: \"SEPA credit transfer\" },\n { code: 59, name: \"SEPA direct debit\" },\n] as const;\n\n/**\n * Get all supported payment means codes.\n *\n * @returns Array of payment means codes sorted by code\n */\nexport function getPaymentMeansCodes(): PaymentMeansCode[] {\n return [...PAYMENT_MEANS_CODES];\n}\n","/**\n * Invoice Validator\n *\n * Validates invoice data BEFORE conversion to XML.\n * Implements key Peppol BIS 3.0 business rules with human-readable error messages.\n *\n * Design principle: Errors tell you WHAT's wrong, WHERE it is, and HOW to fix it.\n * No developer should need to Google a Peppol rule ID.\n */\n\nimport type {\n InvoiceInput,\n InvoiceLine,\n Party,\n ValidationResult,\n ValidationError,\n ValidationWarning,\n} from \"../types/invoice.js\";\nimport { validateCountryRules } from \"./country-rules.js\";\nimport { getCurrency } from \"./code-lists.js\";\n\nfunction error(field: string, message: string, ruleId?: string, suggestion?: string): ValidationError {\n return { field, message, ruleId, suggestion };\n}\n\nfunction warning(field: string, message: string, ruleId?: string): ValidationWarning {\n return { field, message, ruleId };\n}\n\n/**\n * Type-guard that pushes a clean ValidationError when value is not a string.\n * Returns false to signal that downstream string-only checks should be skipped.\n * Prevents raw TypeError bubbling out of the SDK on malformed input (GPR-414 #3).\n */\nfunction assertString(\n value: unknown,\n fieldPath: string,\n errors: ValidationError[],\n): value is string {\n if (typeof value !== \"string\") {\n errors.push(error(\n fieldPath,\n `Expected string, received ${value === null ? \"null\" : typeof value}`,\n undefined,\n \"Check your payload — this field must be a text value\",\n ));\n return false;\n }\n return true;\n}\n\nconst ISO_DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nfunction validateParty(party: Party, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (party.name === undefined || party.name === null || party.name === \"\") {\n errors.push(error(`${path}.name`, \"Business name is required\", \"BR-06\"));\n } else if (!assertString(party.name, `${path}.name`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.name.trim()) {\n errors.push(error(`${path}.name`, \"Business name is required\", \"BR-06\"));\n }\n\n if (party.peppolId === undefined || party.peppolId === null || (party.peppolId as string) === \"\") {\n errors.push(\n error(\n `${path}.peppolId`,\n \"Peppol participant ID is required\",\n undefined,\n 'Format: \"scheme:id\", e.g. \"0208:0685660237\" for Belgian companies'\n )\n );\n } else if (!assertString(party.peppolId, `${path}.peppolId`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.peppolId.includes(\":\")) {\n errors.push(\n error(\n `${path}.peppolId`,\n `Invalid Peppol ID format: \"${party.peppolId}\"`,\n undefined,\n 'Must be \"scheme:id\" format. Common schemes: 0208 (Belgium), 0009 (France SIRET), 0204 (Germany Leitweg)'\n )\n );\n }\n\n if (party.country === undefined || party.country === null || party.country === \"\") {\n errors.push(error(`${path}.country`, \"Country code is required\", \"BR-11\"));\n } else if (!assertString(party.country, `${path}.country`, errors)) {\n // skip — assertString already pushed the type error\n } else if (party.country.length !== 2) {\n errors.push(\n error(\n `${path}.country`,\n `Invalid country code: \"${party.country}\"`,\n undefined,\n \"Must be ISO 3166-1 alpha-2 (e.g., BE, FR, DE, NL)\"\n )\n );\n }\n\n return errors;\n}\n\n/** Validate buyer postal address — required by Peppol BIS 3.0 (BG-8) and Storecove */\nfunction validateBuyerAddress(party: Party, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (party.street === undefined || party.street === null || party.street === \"\") {\n errors.push(error(`${path}.street`, \"Street address is required for the buyer\", \"BR-50\",\n 'e.g. \"123 Business Street\"'));\n } else if (!assertString(party.street, `${path}.street`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.street.trim()) {\n errors.push(error(`${path}.street`, \"Street address is required for the buyer\", \"BR-50\",\n 'e.g. \"123 Business Street\"'));\n }\n\n if (party.city === undefined || party.city === null || party.city === \"\") {\n errors.push(error(`${path}.city`, \"City is required for the buyer\", \"BR-51\",\n 'e.g. \"Brussels\"'));\n } else if (!assertString(party.city, `${path}.city`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.city.trim()) {\n errors.push(error(`${path}.city`, \"City is required for the buyer\", \"BR-51\",\n 'e.g. \"Brussels\"'));\n }\n\n if (party.postalCode === undefined || party.postalCode === null || party.postalCode === \"\") {\n errors.push(error(`${path}.postalCode`, \"Postal code is required for the buyer\", \"BR-53\",\n 'e.g. \"1000\"'));\n } else if (!assertString(party.postalCode, `${path}.postalCode`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!party.postalCode.trim()) {\n errors.push(error(`${path}.postalCode`, \"Postal code is required for the buyer\", \"BR-53\",\n 'e.g. \"1000\"'));\n }\n\n return errors;\n}\n\nfunction validateLine(line: InvoiceLine, index: number, isCreditNote = false): ValidationError[] {\n const errors: ValidationError[] = [];\n const path = `lines[${index}]`;\n\n if (line.description === undefined || line.description === null || line.description === \"\") {\n errors.push(error(`${path}.description`, \"Line item description is required\", \"BR-25\"));\n } else if (!assertString(line.description, `${path}.description`, errors)) {\n // skip — assertString already pushed the type error\n } else if (!line.description.trim()) {\n errors.push(error(`${path}.description`, \"Line item description is required\", \"BR-25\"));\n }\n\n if (line.quantity === undefined || line.quantity === null) {\n errors.push(error(`${path}.quantity`, \"Quantity is required\", \"BR-22\"));\n } else if (line.quantity <= 0 && !isCreditNote) {\n errors.push(\n error(\n `${path}.quantity`,\n `Quantity must be positive, got ${line.quantity}`,\n undefined,\n \"For returns/credits, use a credit note instead\"\n )\n );\n }\n\n if (line.unitPrice === undefined || line.unitPrice === null) {\n errors.push(error(`${path}.unitPrice`, \"Unit price is required\", \"BR-26\"));\n } else if (line.unitPrice < 0) {\n errors.push(\n error(\n `${path}.unitPrice`,\n `Unit price cannot be negative, got ${line.unitPrice}`,\n undefined,\n \"For discounts, use a negative quantity or a separate discount line\"\n )\n );\n }\n\n if (line.vatRate === undefined || line.vatRate === null) {\n errors.push(error(`${path}.vatRate`, \"VAT rate is required\", \"BR-CO-17\"));\n } else if (line.vatRate < 0 || line.vatRate > 100) {\n errors.push(\n error(\n `${path}.vatRate`,\n `VAT rate must be between 0 and 100, got ${line.vatRate}`,\n undefined,\n \"Use 0 for zero-rated, 21 for standard Belgian VAT, etc.\"\n )\n );\n }\n\n return errors;\n}\n\n/**\n * Validate an invoice input before sending.\n * Returns human-readable errors with suggestions for fixes.\n */\nexport function validateInvoice(input: InvoiceInput): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // ── Invoice-level validation ──\n\n if (input.number === undefined || input.number === null || input.number === \"\") {\n errors.push(\n error(\"number\", \"Invoice number is required\", \"BR-02\", \"Must be unique per supplier\")\n );\n } else if (!assertString(input.number, \"number\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!input.number.trim()) {\n errors.push(\n error(\"number\", \"Invoice number is required\", \"BR-02\", \"Must be unique per supplier\")\n );\n }\n\n // ── Invoice type code validation ──\n\n const VALID_TYPE_CODES = [380, 381, 383, 384, 386, 389, 751];\n if (input.invoiceTypeCode != null && !VALID_TYPE_CODES.includes(input.invoiceTypeCode)) {\n errors.push(\n error(\n \"invoiceTypeCode\",\n `Invalid invoice type code: ${input.invoiceTypeCode}`,\n undefined,\n \"Valid codes: 380, 381, 383, 384, 386, 389, 751\"\n )\n );\n }\n\n // ── Credit note validation ──\n\n if (input.isCreditNote) {\n const ref = input.invoiceReference;\n if (ref === undefined || ref === null || ref === \"\") {\n errors.push(error(\n \"invoiceReference\",\n \"Reference to the original invoice is required for credit notes\",\n undefined,\n 'Set invoiceReference to the original invoice number (e.g., \"INV-001\")'\n ));\n } else if (!assertString(ref, \"invoiceReference\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!ref.trim()) {\n errors.push(error(\n \"invoiceReference\",\n \"Reference to the original invoice is required for credit notes\",\n undefined,\n 'Set invoiceReference to the original invoice number (e.g., \"INV-001\")'\n ));\n }\n }\n\n if (input.from) {\n warnings.push(\n warning(\n \"from\",\n \"Seller info is determined by your API key. The 'from' field is deprecated and ignored.\",\n )\n );\n }\n\n if (!input.to) {\n errors.push(error(\"to\", \"Buyer (to) is required\", \"BR-07\"));\n } else {\n errors.push(...validateParty(input.to, \"to\"));\n errors.push(...validateBuyerAddress(input.to, \"to\"));\n }\n\n if (input.payeeParty) {\n const ppName = input.payeeParty.name;\n if (ppName === undefined || ppName === null || ppName === \"\") {\n errors.push(error(\"payeeParty.name\", \"Payee party name is required\", \"BR-17\"));\n } else if (!assertString(ppName, \"payeeParty.name\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!ppName.trim()) {\n errors.push(error(\"payeeParty.name\", \"Payee party name is required\", \"BR-17\"));\n }\n\n const ppId = input.payeeParty.peppolId;\n if (ppId === undefined || ppId === null || (ppId as string) === \"\") {\n errors.push(\n error(\n \"payeeParty.peppolId\",\n \"Payee party Peppol ID is required\",\n undefined,\n 'Format: \"scheme:id\", e.g. \"0208:0685660237\"'\n )\n );\n } else if (!assertString(ppId, \"payeeParty.peppolId\", errors)) {\n // skip — assertString already pushed the type error\n } else if (!ppId.includes(\":\")) {\n errors.push(\n error(\n \"payeeParty.peppolId\",\n `Invalid Peppol ID format: \"${ppId}\"`,\n undefined,\n 'Must be \"scheme:id\" format'\n )\n );\n }\n }\n\n if (!input.lines || input.lines.length === 0) {\n errors.push(\n error(\"lines\", \"At least one line item is required\", \"BR-16\", \"Add items to the lines array\")\n );\n } else {\n for (let i = 0; i < input.lines.length; i++) {\n errors.push(...validateLine(input.lines[i]!, i, input.isCreditNote));\n }\n }\n\n // ── Date validation ──\n\n if (input.date) {\n if (!ISO_DATE_RE.test(input.date)) {\n errors.push(\n error(\"date\", `Invalid date format: \"${input.date}\"`, undefined, \"Use ISO 8601: YYYY-MM-DD\")\n );\n }\n }\n\n if (input.dueDate) {\n if (!ISO_DATE_RE.test(input.dueDate)) {\n errors.push(\n error(\n \"dueDate\",\n `Invalid due date format: \"${input.dueDate}\"`,\n undefined,\n \"Use ISO 8601: YYYY-MM-DD\"\n )\n );\n }\n }\n\n // ── TaxPointDate validation (BT-7) ──\n\n if (input.taxPointDate) {\n if (!ISO_DATE_RE.test(input.taxPointDate)) {\n errors.push(\n error(\n \"taxPointDate\",\n `Invalid tax point date format: \"${input.taxPointDate}\"`,\n undefined,\n \"Use ISO 8601: YYYY-MM-DD\"\n )\n );\n }\n }\n\n // ── RoundingAmount validation (BT-114) ──\n\n if (input.roundingAmount !== undefined && input.roundingAmount !== null) {\n if (input.roundingAmount < -0.99 || input.roundingAmount > 0.99) {\n errors.push(\n error(\n \"roundingAmount\",\n `Rounding amount must be between -0.99 and 0.99, got ${input.roundingAmount}`,\n undefined,\n \"Rounding is stored as integer cents (±99). Use values like 0.50 or -0.25.\"\n )\n );\n }\n }\n\n // ── BuyerReference / OrderReference (BT-10) ──\n\n if (!input.buyerReference && !input.orderReference) {\n warnings.push(\n warning(\n \"buyerReference\",\n \"Either buyerReference or orderReference is required by Peppol BIS 3.0 (BT-10).\",\n \"BR-10\"\n )\n );\n }\n\n // ── TaxCurrencyCode validation ──\n\n if (input.taxCurrency && input.taxCurrency !== (input.currency ?? \"EUR\") && !input.taxCurrencyRate) {\n errors.push(\n error(\n \"taxCurrencyRate\",\n \"Tax currency rate is required when taxCurrency differs from document currency\",\n \"BR-53\",\n \"Set taxCurrencyRate to the exchange rate from document currency to tax currency\"\n )\n );\n }\n\n if (input.taxCurrency && input.taxCurrency === (input.currency ?? \"EUR\")) {\n warnings.push(\n warning(\"taxCurrency\", \"Tax currency is the same as document currency — TaxCurrencyCode will be omitted\")\n );\n }\n\n if (input.taxCurrencyRate !== undefined && input.taxCurrencyRate <= 0) {\n errors.push(\n error(\n \"taxCurrencyRate\",\n `Tax currency rate must be positive, got ${input.taxCurrencyRate}`,\n undefined,\n \"Set to the exchange rate from document currency to tax currency\"\n )\n );\n }\n\n // ── Currency code validation (ISO 4217) ──\n\n if (input.currency && !getCurrency(input.currency)) {\n errors.push(\n error(\n \"currency\",\n `Invalid currency code: \"${input.currency}\"`,\n undefined,\n 'Use ISO 4217 (e.g., \"EUR\", \"USD\", \"GBP\", \"JPY\"). See https://getpeppr.dev/docs/types/#currency'\n )\n );\n }\n\n if (input.taxCurrency && !getCurrency(input.taxCurrency)) {\n errors.push(\n error(\n \"taxCurrency\",\n `Invalid tax currency code: \"${input.taxCurrency}\"`,\n undefined,\n 'Use ISO 4217 (e.g., \"EUR\", \"USD\")'\n )\n );\n }\n\n // ── Warnings (non-blocking) ──\n\n if (!input.dueDate) {\n warnings.push(warning(\"dueDate\", \"No due date specified. Recommended for payment terms.\", \"BR-09\"));\n }\n\n if (!input.to?.vatNumber) {\n warnings.push(warning(\"to.vatNumber\", \"Buyer VAT number not provided. May be required for B2B.\"));\n }\n\n if (input.paymentMeans === 30 && !input.paymentIban) {\n warnings.push(\n warning(\n \"paymentIban\",\n \"Payment means is credit transfer but no IBAN provided. Buyer won't know where to pay.\"\n )\n );\n }\n\n // ── Cross-field validation ──\n\n if (input.from?.peppolId && input.to?.peppolId && input.from.peppolId === input.to.peppolId) {\n errors.push(\n error(\n \"to.peppolId\",\n \"Buyer and seller cannot have the same Peppol ID\",\n undefined,\n \"Check that 'from' and 'to' are different parties\"\n )\n );\n }\n\n // ── Country-specific rules (advisory warnings) ──\n\n const countryResult = validateCountryRules(input);\n warnings.push(...countryResult.warnings);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","/** SDK version — keep in sync with package.json on each release. */\nexport const SDK_VERSION = \"2.0.0\";\n","/**\n * getpeppr SDK Client\n *\n * The main entry point. Designed to feel like Stripe's SDK:\n *\n * const peppol = new Peppol({ apiKey: \"sk_live_...\" });\n * const result = await peppol.invoices.send({ from, to, lines });\n *\n * All requests go through the getpeppr API gateway (api.getpeppr.dev),\n * which handles Peppol delivery, billing, and usage tracking.\n * Use `baseUrl` to point to a custom instance or localhost.\n */\n\nimport type {\n PeppolConfig,\n InvoiceInput,\n CreditNoteInput,\n SendResult,\n ValidationResult,\n WebhookEvent,\n RetryConfig,\n DocumentStatus,\n WaitForOptions,\n PaginatedResult,\n InvoiceSummary,\n ListInvoicesOptions,\n DirectoryEntry,\n DirectorySearchOptions,\n DirectorySearchResult,\n PeppolId,\n DocumentFormat,\n ServerValidationResult,\n EventEntry,\n ListEventsOptions,\n BatchSendOptions,\n BatchSendResult,\n InvoiceOperationOptions,\n RequestLogEntry,\n ResponseLogEntry,\n Contact,\n ContactInput,\n ListContactsOptions,\n BankAccount,\n BankAccountInput,\n ListBankAccountsOptions,\n ImportInvoiceOptions,\n TransportType,\n Transport,\n TransportInput,\n TransportUpdateInput,\n MarkAsState,\n MarkAsOptions,\n InvoiceUpdateInput,\n LegalEntityInput,\n LegalEntity,\n LegalEntityStatus,\n ListLegalEntitiesOptions,\n ArchiveLegalEntityResult,\n AttestationInput,\n AttestationResult,\n LegalEntityRequestOptions,\n} from \"../types/invoice.js\";\nimport { buildInvoiceXml, buildCreditNoteXml } from \"./ubl-builder.js\";\nimport { validateInvoice } from \"./validator.js\";\nimport { SDK_VERSION } from \"../version.js\";\n\n// ─── Backend Adapter Interface ──────────────────────────────\n\n/**\n * Backend adapter interface for the SDK's transport layer.\n * The default implementation hits the getpeppr API gateway.\n *\n * @internal transport contract. This interface is NOT meant to be implemented by\n * consumers — `PeppolConfig` exposes no adapter injection point, so the only\n * implementer is the built-in `GetpepprAdapter`. New gateway features add methods\n * here as minor releases (as contacts/bank-accounts/transports did); external\n * `implements BackendAdapter` is unsupported and may break across minor versions.\n */\nexport interface BackendAdapter {\n /** Provider name (for logging) */\n readonly name: string;\n /** Send an invoice as structured JSON (gateway handles UBL generation) */\n sendInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult>;\n /** Create a draft invoice without sending (POST /invoices, no send_after_import) */\n createInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult>;\n /** Send an existing draft invoice by ID (POST /invoices/send/{id}, returns 204) */\n sendInvoiceById(id: string): Promise<void>;\n /** @deprecated Credit notes now route through sendInvoice with isCreditNote: true */\n sendCreditNote(input: CreditNoteInput): Promise<SendResult>;\n /** Validate an invoice server-side (free, no metering) */\n validateDocument(input: InvoiceInput): Promise<{ valid: boolean; errors: string[] }>;\n /** List invoices with pagination and filtering */\n listInvoices(options?: ListInvoicesOptions): Promise<PaginatedResult<InvoiceSummary>>;\n /** Get document status by ID */\n getStatus(documentId: string): Promise<SendResult>;\n /** Look up a Peppol participant in the directory */\n lookupDirectory(scheme: string, id: string): Promise<DirectoryEntry>;\n /** Search the Peppol Directory for participants */\n searchDirectory?(params: Record<string, string>): Promise<DirectorySearchResult>;\n /** Export an invoice in a specific format (e.g., PDF) — returns raw binary */\n getInvoiceAs(id: string, format: DocumentFormat): Promise<ArrayBuffer>;\n /** Validate an invoice server-side through the getpeppr gateway's offline SDK-backed checks. */\n validateDocumentServer(input: InvoiceInput): Promise<ServerValidationResult>;\n /** List events with optional filtering and pagination */\n listEvents(options?: ListEventsOptions): Promise<PaginatedResult<EventEntry>>;\n /** Acknowledge a received invoice (POST /invoices/{id}/ack) */\n acknowledgeInvoice(id: string): Promise<SendResult>;\n /** List contacts with optional filtering and pagination */\n listContacts(options?: ListContactsOptions): Promise<PaginatedResult<Contact>>;\n /** Get a single contact by ID */\n getContact(id: string): Promise<Contact>;\n /** Create a new contact */\n createContact(input: ContactInput): Promise<Contact>;\n /** Update an existing contact */\n updateContact(id: string, input: Partial<ContactInput>): Promise<Contact>;\n /** Delete a contact */\n deleteContact(id: string): Promise<void>;\n /** List bank accounts with optional pagination */\n listBankAccounts(options?: ListBankAccountsOptions): Promise<PaginatedResult<BankAccount>>;\n /** Get a single bank account by ID */\n getBankAccount(id: string): Promise<BankAccount>;\n /** Create a new bank account */\n createBankAccount(input: BankAccountInput): Promise<BankAccount>;\n /** Update an existing bank account */\n updateBankAccount(id: string, input: Partial<BankAccountInput>): Promise<BankAccount>;\n /** Delete a bank account */\n deleteBankAccount(id: string): Promise<void>;\n /** Import an invoice from a file (XML, PDF, etc.) */\n importInvoice(options: ImportInvoiceOptions): Promise<SendResult>;\n /** List all available transport types (global, not account-scoped) */\n listTransportTypes(): Promise<TransportType[]>;\n /** List configured transports for this account */\n listTransports(): Promise<Transport[]>;\n /** Get a single transport by code */\n getTransport(code: string): Promise<Transport>;\n /** Create a new transport */\n createTransport(input: TransportInput): Promise<Transport>;\n /** Update an existing transport */\n updateTransport(code: string, input: TransportUpdateInput): Promise<Transport>;\n /** Delete a transport */\n deleteTransport(code: string): Promise<void>;\n /** Update an existing invoice */\n updateInvoice(id: string, input: InvoiceUpdateInput): Promise<SendResult>;\n /** Delete an invoice */\n deleteInvoice(id: string): Promise<SendResult>;\n /** Transition an invoice to a new state */\n markInvoiceAs(id: string, state: MarkAsState, options?: MarkAsOptions): Promise<SendResult>;\n /** Create a sub-tenant Legal Entity (master key). */\n createLegalEntity(input: LegalEntityInput, options?: LegalEntityRequestOptions): Promise<LegalEntity>;\n /** Fetch a single sub-tenant Legal Entity by id (master key). */\n getLegalEntity(id: string): Promise<LegalEntity>;\n /** List sub-tenant Legal Entities (master key), paginated. */\n listLegalEntities(options?: ListLegalEntitiesOptions): Promise<PaginatedResult<LegalEntity>>;\n /** Archive (soft-delete) a sub-tenant Legal Entity (master key). */\n archiveLegalEntity(id: string): Promise<ArchiveLegalEntityResult>;\n /** Request (or resend) a sub-tenant attestation — production only (master key). */\n requestLegalEntityAttestation(id: string, input: AttestationInput, options?: LegalEntityRequestOptions): Promise<AttestationResult>;\n}\n\n// ─── Retry & Header Utilities ────────────────────────────────────────\n\n/**\n * Case-insensitive header lookup. Per RFC 7230 §3.2, HTTP header names are\n * case-insensitive. Some adapters (axios default, Cloudflare Workers, proxies) lowercase\n * header keys, which made the strict bracket lookup miss user-supplied lowercase\n * keys and silently disabled retry safety on POST requests with idempotency keys.\n *\n * When multiple headers match (e.g. \"Idempotency-Key\" and \"idempotency-key\" both present),\n * returns the value of the first matching key in insertion order.\n *\n * @internal — exported for testing only; not part of the public SDK surface.\n */\nexport function findHeaderCaseInsensitive(\n headers: Record<string, string> | undefined,\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n const target = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === target) return value;\n }\n return undefined;\n}\n\nconst RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction calculateRetryDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n retryAfterMs?: number,\n): number {\n if (retryAfterMs !== undefined) return Math.min(retryAfterMs, maxDelayMs);\n const exponentialDelay = initialDelayMs * Math.pow(2, attempt);\n const jitter = Math.random() * initialDelayMs;\n return Math.min(exponentialDelay + jitter, maxDelayMs);\n}\n\n/**\n * Parse the Retry-After header value into milliseconds.\n * Supports integer seconds (e.g., \"1\", \"60\") and HTTP-date format.\n * Returns undefined if the header is missing or unparseable.\n */\nfunction parseRetryAfter(headerValue: string | null): number | undefined {\n if (!headerValue) return undefined;\n\n // Try integer seconds first (most common for rate limiters)\n const seconds = Number(headerValue);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n // Try HTTP-date format (e.g., \"Wed, 21 Oct 2025 07:28:00 GMT\")\n const dateMs = Date.parse(headerValue);\n if (!Number.isNaN(dateMs)) {\n const delayMs = dateMs - Date.now();\n return delayMs > 0 ? delayMs : 0;\n }\n\n return undefined;\n}\n\nfunction isRetryableError(error: unknown): boolean {\n if (error instanceof PeppolApiError) {\n return RETRYABLE_STATUS_CODES.has(error.statusCode);\n }\n // Retry on timeout/abort errors\n if (error instanceof Error && error.name === \"AbortError\") {\n return true;\n }\n // Retry on transient network errors (DNS failure, connection refused, reset, timeout, etc.)\n if (error instanceof TypeError && /fetch failed|network|ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT/i.test(error.message)) {\n return true;\n }\n return false;\n}\n\n// ─── getpeppr API Adapter ───────────────────────────────────\n\nconst DEFAULT_BASE_URL = \"https://api.getpeppr.dev/v1\";\n\nclass GetpepprAdapter implements BackendAdapter {\n readonly name = \"getpeppr\";\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private retryConfig: Required<RetryConfig>;\n private onRequest?: (entry: RequestLogEntry) => void;\n private onResponse?: (entry: ResponseLogEntry) => void;\n\n constructor(config: PeppolConfig) {\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 30_000;\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.retryConfig = {\n maxRetries: config.retry?.maxRetries ?? 3,\n initialDelayMs: config.retry?.initialDelayMs ?? 500,\n maxDelayMs: config.retry?.maxDelayMs ?? 30_000,\n };\n this.onRequest = config.onRequest;\n this.onResponse = config.onResponse;\n }\n\n private async request<T>(method: string, path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T> {\n const { maxRetries, initialDelayMs, maxDelayMs } = this.retryConfig;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await this.doRequest<T>(method, path, body, extraHeaders);\n } catch (err) {\n lastError = err;\n // 429 (rate limit) is always safe to retry — the request was never processed.\n // For other retryable errors (500, 502, 503, 504, network failures),\n // only retry non-idempotent methods (POST, PUT, PATCH) if an Idempotency-Key was\n // provided, to prevent duplicate side effects (e.g., sending the same invoice twice).\n const is429 = err instanceof PeppolApiError && err.statusCode === 429;\n const isSafeMethod = /^(GET|DELETE|HEAD)$/i.test(method);\n const hasIdempotencyKey = !!findHeaderCaseInsensitive(extraHeaders, \"Idempotency-Key\");\n const canRetry = is429 || isSafeMethod || hasIdempotencyKey;\n if (attempt < maxRetries && canRetry && isRetryableError(err)) {\n const retryAfterMs = err instanceof PeppolApiError ? err.retryAfterMs : undefined;\n await sleep(calculateRetryDelay(attempt, initialDelayMs, maxDelayMs, retryAfterMs));\n continue;\n }\n throw err;\n }\n }\n\n throw lastError;\n }\n\n private async doRequest<T>(method: string, path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const requestHeaders: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": `getpeppr-sdk/${SDK_VERSION}`,\n ...extraHeaders,\n };\n\n const startTime = Date.now();\n if (this.onRequest) {\n try {\n this.onRequest({\n method,\n url,\n headers: { ...requestHeaders },\n body,\n timestamp: startTime,\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers: requestHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"Unknown error\");\n const retryAfterMs = response.status === 429\n ? parseRetryAfter(response.headers.get(\"Retry-After\"))\n : undefined;\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: errorBody,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n throw new PeppolApiError(\n `getpeppr API error (${response.status}): ${errorBody}`,\n response.status,\n errorBody,\n retryAfterMs,\n );\n }\n\n // 204 No Content — no body to parse (e.g., sendInvoiceById)\n if (response.status === 204) {\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: undefined,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n return undefined as T;\n }\n\n let responseBody: T;\n try {\n responseBody = (await response.json()) as T;\n } catch {\n throw new PeppolApiError(\n `getpeppr API error: unexpected response format (status ${response.status})`,\n response.status,\n \"Response body is not valid JSON\",\n );\n }\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: responseBody,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n return responseBody;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n // NOTE: sendInvoice and createInvoice hit the same SDK endpoint (POST /invoices).\n // The gateway (Tasks 9-10) differentiates them: sendInvoice wraps with\n // { invoice: {...}, send_after_import: true }, createInvoice omits the flag.\n async sendInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n const headers: Record<string, string> = {};\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n }\n if (options?.validateRecipient) {\n headers[\"X-Validate-Recipient\"] = options.validateRecipient === true ? \"warn\" : String(options.validateRecipient);\n }\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/invoices\", input, headers);\n return parseSendResult(result);\n }\n\n async createInvoice(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n const headers: Record<string, string> = {};\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n }\n if (options?.validateRecipient) {\n headers[\"X-Validate-Recipient\"] = options.validateRecipient === true ? \"warn\" : String(options.validateRecipient);\n }\n // Signal to the gateway that this is a draft (no auto-send).\n // The gateway reads `_draft` and strips it before forwarding to the provider.\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/invoices\", { ...input, _draft: true }, headers);\n return parseSendResult(result);\n }\n\n async sendInvoiceById(id: string): Promise<void> {\n await this.request<void>(\"POST\", `/invoices/send/${id}`);\n }\n\n async sendCreditNote(input: CreditNoteInput): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/credit-notes\", input);\n return parseSendResult(result);\n }\n\n async validateDocument(input: InvoiceInput): Promise<{ valid: boolean; errors: string[] }> {\n return this.request<{ valid: boolean; errors: string[] }>(\"POST\", \"/validate\", input);\n }\n\n async listInvoices(options?: ListInvoicesOptions): Promise<PaginatedResult<InvoiceSummary>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n if (options?.includeLines) params.set(\"include\", \"lines\");\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/invoices${query}`);\n\n // Gateway returns { invoices: [...], meta: {...} }\n const invoices = (result.invoices ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: invoices.map(parseInvoiceSummary),\n meta: {\n totalCount: Number(meta?.total_count ?? invoices.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta ? Number(meta.total_count) > Number(meta.offset) + Number(meta.limit) : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async getStatus(documentId: string): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/invoices/${documentId}`);\n return parseSendResult(result);\n }\n\n async lookupDirectory(scheme: string, id: string): Promise<DirectoryEntry> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/directory/${scheme}/${id}`);\n return parseDirectoryEntry(result);\n }\n\n async searchDirectory(params: Record<string, string>): Promise<DirectorySearchResult> {\n const query = new URLSearchParams(params).toString();\n return this.request<DirectorySearchResult>(\"GET\", `/directory/search?${query}`);\n }\n\n async getInvoiceAs(id: string, format: DocumentFormat): Promise<ArrayBuffer> {\n const { maxRetries, initialDelayMs, maxDelayMs } = this.retryConfig;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await this.doRequestBinary(`/invoices/${id}/as/${format}`);\n } catch (err) {\n lastError = err;\n if (attempt < maxRetries && isRetryableError(err)) {\n const retryAfterMs = err instanceof PeppolApiError ? err.retryAfterMs : undefined;\n await sleep(calculateRetryDelay(attempt, initialDelayMs, maxDelayMs, retryAfterMs));\n continue;\n }\n throw err;\n }\n }\n\n throw lastError;\n }\n\n private async doRequestBinary(path: string): Promise<ArrayBuffer> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const requestHeaders = {\n Authorization: `Bearer ${this.apiKey}`,\n };\n\n const startTime = Date.now();\n if (this.onRequest) {\n try {\n this.onRequest({\n method: \"GET\",\n url,\n headers: { ...requestHeaders },\n timestamp: startTime,\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: requestHeaders,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"Unknown error\");\n const retryAfterMs = response.status === 429\n ? parseRetryAfter(response.headers.get(\"Retry-After\"))\n : undefined;\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: errorBody,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n throw new PeppolApiError(\n `getpeppr API error (${response.status}): ${errorBody}`,\n response.status,\n errorBody,\n retryAfterMs,\n );\n }\n\n const responseBody = await response.arrayBuffer();\n\n if (this.onResponse) {\n try {\n this.onResponse({\n status: response.status,\n headers: Object.fromEntries(response.headers.entries()),\n body: `[ArrayBuffer: ${responseBody.byteLength} bytes]`,\n durationMs: Date.now() - startTime,\n timestamp: Date.now(),\n });\n } catch {\n // Hook errors must never break the request\n }\n }\n\n return responseBody;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async validateDocumentServer(input: InvoiceInput): Promise<ServerValidationResult> {\n return this.request<ServerValidationResult>(\"POST\", \"/validate/server\", input);\n }\n\n async listEvents(options?: ListEventsOptions): Promise<PaginatedResult<EventEntry>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n if (options?.invoiceId) params.set(\"invoiceId\", options.invoiceId);\n if (options?.dateFrom) params.set(\"dateFrom\", options.dateFrom);\n if (options?.dateTo) params.set(\"dateTo\", options.dateTo);\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/events${query}`);\n\n // Rows are camelCase (id, eventType, documentId, metadata, createdAt);\n // pagination meta is snake_case (total_count, has_more) — same split as\n // invoices.list (GPR-738). Read both forms defensively.\n const events = (result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: events.map((evt) => ({\n id: String(evt.id ?? \"\"),\n eventType: String(evt.eventType ?? evt.event_type ?? \"\"),\n documentId: (evt.documentId ?? evt.document_id ?? null) as string | null,\n metadata: (evt.metadata ?? null) as Record<string, unknown> | null,\n createdAt: String(evt.createdAt ?? evt.created_at ?? \"\"),\n })),\n meta: {\n totalCount: Number(meta?.total_count ?? meta?.totalCount ?? events.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n // Prefer the gateway's authoritative has_more; fall back to computing it\n // from total_count/offset/limit so listAll() paginates correctly even if\n // a response omits the flag.\n hasMore:\n meta?.has_more != null || meta?.hasMore != null\n ? Boolean(meta.has_more ?? meta.hasMore)\n : Number(meta?.total_count ?? meta?.totalCount ?? 0) >\n Number(meta?.offset ?? options?.offset ?? 0) +\n Number(meta?.limit ?? options?.limit ?? 0),\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async acknowledgeInvoice(id: string): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"POST\", `/invoices/${id}/ack`);\n return parseSendResult(result);\n }\n\n async updateInvoice(id: string, input: InvoiceUpdateInput): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/invoices/${id}`, input);\n return parseSendResult(result);\n }\n\n async deleteInvoice(id: string): Promise<SendResult> {\n const result = await this.request<Record<string, unknown>>(\"DELETE\", `/invoices/${id}`);\n return parseSendResult(result);\n }\n\n async markInvoiceAs(id: string, state: MarkAsState, options?: MarkAsOptions): Promise<SendResult> {\n const body: Record<string, unknown> = { state };\n if (options?.commit) body.commit = options.commit;\n if (options?.reason) body.reason = options.reason;\n const result = await this.request<Record<string, unknown>>(\"POST\", `/invoices/${id}/mark-as`, body);\n return parseSendResult(result);\n }\n\n async listContacts(options?: ListContactsOptions): Promise<PaginatedResult<Contact>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n if (options?.name) params.set(\"name\", options.name);\n if (options?.isClient != null) params.set(\"isClient\", String(options.isClient));\n if (options?.isProvider != null) params.set(\"isProvider\", String(options.isProvider));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/contacts${query}`);\n\n const contacts = (result.contacts ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: contacts.map(parseContact),\n meta: {\n totalCount: Number(meta?.total_count ?? meta?.totalCount ?? contacts.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta\n ? Number(meta.total_count ?? meta.totalCount) > Number(meta.offset) + Number(meta.limit)\n : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async getContact(id: string): Promise<Contact> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/contacts/${id}`);\n return parseContact(result);\n }\n\n async createContact(input: ContactInput): Promise<Contact> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/contacts\", input);\n return parseContact(result);\n }\n\n async updateContact(id: string, input: Partial<ContactInput>): Promise<Contact> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/contacts/${id}`, input);\n return parseContact(result);\n }\n\n async deleteContact(id: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/contacts/${id}`);\n }\n\n async createLegalEntity(input: LegalEntityInput, options?: LegalEntityRequestOptions): Promise<LegalEntity> {\n const headers: Record<string, string> = {};\n if (options?.idempotencyKey) headers[\"Idempotency-Key\"] = options.idempotencyKey;\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/legal-entities\", input, headers);\n return parseLegalEntity(result);\n }\n\n async getLegalEntity(id: string): Promise<LegalEntity> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/legal-entities/${id}`);\n return parseLegalEntity(result);\n }\n\n async listLegalEntities(options?: ListLegalEntitiesOptions): Promise<PaginatedResult<LegalEntity>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/legal-entities${query}`);\n\n // The route returns { data, pagination: { total_count, offset, limit, has_more } }.\n const rows = (result.data ?? []) as Record<string, unknown>[];\n const pagination = result.pagination as Record<string, unknown> | undefined;\n\n return {\n data: rows.map(parseLegalEntity),\n meta: {\n totalCount: Number(pagination?.total_count ?? rows.length),\n offset: Number(pagination?.offset ?? options?.offset ?? 0),\n limit: Number(pagination?.limit ?? options?.limit ?? 50),\n hasMore: Boolean(pagination?.has_more ?? false),\n truncated: false,\n },\n };\n }\n\n async archiveLegalEntity(id: string): Promise<ArchiveLegalEntityResult> {\n const result = await this.request<Record<string, unknown>>(\"DELETE\", `/legal-entities/${id}`);\n return {\n id: String(result.id ?? id),\n externalId: result.externalId != null ? String(result.externalId) : null,\n status: \"archived\",\n };\n }\n\n async requestLegalEntityAttestation(id: string, input: AttestationInput, options?: LegalEntityRequestOptions): Promise<AttestationResult> {\n const headers: Record<string, string> = {};\n if (options?.idempotencyKey) headers[\"Idempotency-Key\"] = options.idempotencyKey;\n const result = await this.request<Record<string, unknown>>(\n \"POST\",\n `/legal-entities/${id}/attestation`,\n input,\n headers,\n );\n return {\n id: String(result.id ?? id),\n externalId: result.externalId != null ? String(result.externalId) : null,\n status: String(result.status ?? \"\") as LegalEntityStatus,\n expiresAt: String(result.expiresAt ?? \"\"),\n };\n }\n\n async listBankAccounts(options?: ListBankAccountsOptions): Promise<PaginatedResult<BankAccount>> {\n const params = new URLSearchParams();\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n if (options?.offset != null) params.set(\"offset\", String(options.offset));\n const query = params.toString() ? `?${params.toString()}` : \"\";\n\n const result = await this.request<Record<string, unknown>>(\"GET\", `/bank-accounts${query}`);\n\n const bankAccounts = (result.bankAccounts ?? result.data ?? []) as Record<string, unknown>[];\n const meta = result.meta as Record<string, unknown> | undefined;\n\n return {\n data: bankAccounts.map(parseBankAccount),\n meta: {\n totalCount: Number(meta?.total_count ?? meta?.totalCount ?? bankAccounts.length),\n offset: Number(meta?.offset ?? options?.offset ?? 0),\n limit: Number(meta?.limit ?? options?.limit ?? 25),\n hasMore: meta\n ? Number(meta.total_count ?? meta.totalCount) > Number(meta.offset) + Number(meta.limit)\n : false,\n truncated: Boolean(meta?.truncated ?? false),\n },\n };\n }\n\n async getBankAccount(id: string): Promise<BankAccount> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/bank-accounts/${id}`);\n return parseBankAccount(result);\n }\n\n async createBankAccount(input: BankAccountInput): Promise<BankAccount> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/bank-accounts\", input);\n return parseBankAccount(result);\n }\n\n async updateBankAccount(id: string, input: Partial<BankAccountInput>): Promise<BankAccount> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/bank-accounts/${id}`, input);\n return parseBankAccount(result);\n }\n\n async deleteBankAccount(id: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/bank-accounts/${id}`);\n }\n\n async importInvoice(options: ImportInvoiceOptions): Promise<SendResult> {\n const body = {\n file: arrayBufferToBase64(options.file),\n filename: options.filename,\n mimeType: options.mimeType ?? detectMimeType(options.filename),\n };\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/invoices/import\", body);\n return parseSendResult(result);\n }\n\n async listTransportTypes(): Promise<TransportType[]> {\n const result = await this.request<Record<string, unknown>>(\"GET\", \"/transports/types\");\n const types = (result.transportTypes ?? result.data ?? []) as Record<string, unknown>[];\n return types.map((t) => ({\n code: String(t.code ?? \"\"),\n name: String(t.name ?? \"\"),\n }));\n }\n\n async listTransports(): Promise<Transport[]> {\n const result = await this.request<Record<string, unknown>>(\"GET\", \"/transports\");\n const transports = (result.transports ?? result.data ?? []) as Record<string, unknown>[];\n return transports.map(parseTransport);\n }\n\n async getTransport(code: string): Promise<Transport> {\n const result = await this.request<Record<string, unknown>>(\"GET\", `/transports/${code}`);\n return parseTransport(result);\n }\n\n async createTransport(input: TransportInput): Promise<Transport> {\n const result = await this.request<Record<string, unknown>>(\"POST\", \"/transports\", input);\n return parseTransport(result);\n }\n\n async updateTransport(code: string, input: TransportUpdateInput): Promise<Transport> {\n const result = await this.request<Record<string, unknown>>(\"PUT\", `/transports/${code}`, input);\n return parseTransport(result);\n }\n\n async deleteTransport(code: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/transports/${code}`);\n }\n}\n\n// ─── Import Helpers ──────────────────────────────────────────\n\n/** Convert ArrayBuffer or Uint8Array to base64 string (works in all runtimes). */\nexport function arrayBufferToBase64(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/** Detect MIME type from a filename's extension. */\nexport function detectMimeType(filename: string): string {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n switch (ext) {\n case \"xml\": return \"application/xml\";\n case \"pdf\": return \"application/pdf\";\n case \"json\": return \"application/json\";\n default: return \"application/octet-stream\";\n }\n}\n\nfunction parseSendResult(result: Record<string, unknown>): SendResult {\n return {\n id: String(result.id ?? \"\"),\n status: mapStatus(String(result.status ?? \"submitted\")),\n peppolMessageId: (result.peppolMessageId ?? result.peppol_message_id) as string | undefined,\n createdAt: String(result.createdAt ?? result.updatedAt ?? result.created_at ?? new Date().toISOString()),\n ublXml: result.ublXml as string | undefined,\n warnings: Array.isArray(result.warnings) ? result.warnings : undefined,\n };\n}\n\nfunction parseDirectoryEntry(result: Record<string, unknown>): DirectoryEntry {\n const participant = isRecord(result.participant) ? result.participant : result;\n const scheme = participant.scheme == null ? undefined : String(participant.scheme);\n const id = participant.id == null ? undefined : String(participant.id);\n const peppolId =\n participant.peppolId == null\n ? formatPeppolId(scheme, id)\n : String(participant.peppolId);\n\n return {\n name: String(participant.name ?? \"\"),\n peppolId: peppolId as PeppolId,\n country: String(participant.country ?? \"\"),\n capabilities: Array.isArray(participant.capabilities)\n ? participant.capabilities.map(String)\n : [],\n registrationDate: participant.registrationDate == null ? undefined : String(participant.registrationDate),\n vatNumber: participant.vatNumber == null ? undefined : String(participant.vatNumber),\n additionalIds: Array.isArray(participant.additionalIds)\n ? participant.additionalIds.filter(isRecord).map((entry) => ({\n scheme: String(entry.scheme ?? \"\"),\n value: String(entry.value ?? \"\"),\n }))\n : undefined,\n contactInfo: isRecord(participant.contactInfo)\n ? {\n name: participant.contactInfo.name == null ? undefined : String(participant.contactInfo.name),\n email: participant.contactInfo.email == null ? undefined : String(participant.contactInfo.email),\n phone: participant.contactInfo.phone == null ? undefined : String(participant.contactInfo.phone),\n }\n : undefined,\n website: participant.website == null ? undefined : String(participant.website),\n };\n}\n\nfunction formatPeppolId(scheme: string | undefined, id: string | undefined): string {\n if (!id) return scheme ? `${scheme}:` : \"\";\n if (id.includes(\":\")) return id;\n return scheme ? `${scheme}:${id}` : id;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseContact(raw: Record<string, unknown>): Contact {\n const contact: Contact = {\n id: String(raw.id ?? \"\"),\n name: String(raw.name ?? \"\"),\n };\n\n if (raw.peppolId != null) contact.peppolId = String(raw.peppolId);\n if (raw.vatNumber != null) contact.vatNumber = String(raw.vatNumber);\n if (raw.companyId != null) contact.companyId = String(raw.companyId);\n if (raw.street != null) contact.street = String(raw.street);\n if (raw.city != null) contact.city = String(raw.city);\n if (raw.postalCode != null) contact.postalCode = String(raw.postalCode);\n if (raw.country != null) contact.country = String(raw.country);\n if (raw.email != null) contact.email = String(raw.email);\n if (raw.phone != null) contact.phone = String(raw.phone);\n if (raw.isClient != null) contact.isClient = Boolean(raw.isClient);\n if (raw.isProvider != null) contact.isProvider = Boolean(raw.isProvider);\n if (raw.createdAt != null) contact.createdAt = String(raw.createdAt);\n if (raw.updatedAt != null) contact.updatedAt = String(raw.updatedAt);\n if (raw.directoryVerified != null) contact.directoryVerified = Boolean(raw.directoryVerified);\n if (raw.directoryLastChecked != null) contact.directoryLastChecked = String(raw.directoryLastChecked);\n\n return contact;\n}\n\nfunction parseLegalEntity(raw: Record<string, unknown>): LegalEntity {\n const idObj = raw.identifier as Record<string, unknown> | null | undefined;\n const le: LegalEntity = {\n id: String(raw.id ?? \"\"),\n externalId: raw.externalId != null ? String(raw.externalId) : null,\n companyName: raw.companyName != null ? String(raw.companyName) : null,\n country: raw.country != null ? String(raw.country) : null,\n identifier:\n idObj && idObj.scheme != null && idObj.value != null\n ? { scheme: String(idObj.scheme), value: String(idObj.value) }\n : null,\n status: String(raw.status ?? \"pending\") as LegalEntityStatus,\n environment: String(raw.environment ?? \"\"),\n createdAt: String(raw.createdAt ?? \"\"),\n };\n if (raw.verificationDetail != null) {\n le.verificationDetail = raw.verificationDetail as LegalEntity[\"verificationDetail\"];\n }\n return le;\n}\n\nfunction parseInvoiceSummary(raw: Record<string, unknown>): InvoiceSummary {\n // The gateway returns camelCase rows (`invoiceNumber`, `createdAt`, …);\n // `number` is accepted as a legacy fallback for back-compat (GPR-738).\n const summary: InvoiceSummary = {\n id: String(raw.id ?? \"\"),\n number: String(raw.invoiceNumber ?? raw.number ?? \"\"),\n status: mapStatus(String(raw.state ?? raw.status ?? \"submitted\")),\n };\n if (raw.createdAt != null) summary.createdAt = String(raw.createdAt);\n if (typeof raw.isCreditNote === \"boolean\") summary.isCreditNote = raw.isCreditNote;\n if (raw.recipientName != null) summary.recipientName = String(raw.recipientName);\n if (raw.totalAmount != null && Number.isFinite(Number(raw.totalAmount))) {\n summary.totalAmount = Number(raw.totalAmount);\n }\n if (raw.currency != null) summary.currency = String(raw.currency);\n if (raw.environment != null) summary.environment = String(raw.environment);\n return summary;\n}\n\nfunction parseBankAccount(raw: Record<string, unknown>): BankAccount {\n const account: BankAccount = {\n id: String(raw.id ?? \"\"),\n name: String(raw.name ?? \"\"),\n type: (raw.type === \"number\" ? \"number\" : \"iban\") as \"iban\" | \"number\",\n };\n\n if (raw.iban != null) account.iban = String(raw.iban);\n if (raw.number != null) account.number = String(raw.number);\n if (raw.bic != null) account.bic = String(raw.bic);\n if (raw.country != null) account.country = String(raw.country);\n if (raw.createdAt != null) account.createdAt = String(raw.createdAt);\n if (raw.updatedAt != null) account.updatedAt = String(raw.updatedAt);\n\n return account;\n}\n\nfunction parseTransport(raw: Record<string, unknown>): Transport {\n return {\n id: String(raw.id ?? \"\"),\n transportTypeCode: String(raw.transportTypeCode ?? \"\"),\n name: String(raw.name ?? \"\"),\n status: raw.status ? String(raw.status) : undefined,\n };\n}\n\n// getpeppr gateway document lifecycle states.\n// Mapped from Storecove webhook events. See: Storecove API v2 §3.3.4\nconst VALID_STATUSES = new Set<DocumentStatus>([\n \"submitted\", \"delivered\", \"accepted\", \"rejected\", \"paid\", \"failed\",\n \"cleared\", \"acknowledged\", \"in_process\", \"under_query\",\n \"conditionally_accepted\", \"partially_paid\", \"no_action\",\n \"unknown\", // explicitly known: gateway may emit this when it can't map a Storecove status\n]);\n\n// Note: each call to mapStatus that hits the unknown fallback emits its own console.warn.\n// No dedup is intentional — callers see the warning proportionally to how often the\n// unknown status appears (matches Stripe/AWS SDK convention).\n/** @internal — exported for testing only; not part of the public SDK surface. */\nexport function mapStatus(raw: string): DocumentStatus {\n const s = raw.toLowerCase() as DocumentStatus;\n if (VALID_STATUSES.has(s)) return s;\n console.warn(\n `[getpeppr] Unknown gateway status received: \"${raw}\" — ` +\n `please report to support@getpeppr.dev. Coercing to \"unknown\".`,\n );\n return \"unknown\";\n}\n\n// ─── Error Classes ──────────────────────────────────────────\n\nexport class PeppolError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PeppolError\";\n }\n}\n\nexport class PeppolValidationError extends PeppolError {\n constructor(\n message: string,\n public readonly validation: ValidationResult\n ) {\n super(message);\n this.name = \"PeppolValidationError\";\n }\n}\n\nexport class PeppolApiError extends PeppolError {\n /** Parsed Retry-After delay in milliseconds (present on 429 responses) */\n public readonly retryAfterMs?: number;\n\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly responseBody: string,\n retryAfterMs?: number,\n ) {\n super(message);\n this.name = \"PeppolApiError\";\n this.retryAfterMs = retryAfterMs;\n }\n\n /**\n * The gateway's machine-readable error code, parsed from the JSON response body\n * (e.g. \"le_cap_exceeded\", \"identifier_immutable\", \"legal_entity_locked\", \"forbidden\").\n * Returns undefined when the body is not JSON or carries no string `code`.\n */\n get code(): string | undefined {\n try {\n const parsed = JSON.parse(this.responseBody) as { code?: unknown };\n return typeof parsed?.code === \"string\" ? parsed.code : undefined;\n } catch {\n return undefined;\n }\n }\n}\n\n// ─── Main SDK Client ────────────────────────────────────────\n\nexport class Peppol {\n private adapter: BackendAdapter;\n public readonly invoices: InvoiceOperations;\n public readonly creditNotes: CreditNoteOperations;\n public readonly directory: DirectoryOperations;\n public readonly events: EventOperations;\n public readonly contacts: ContactOperations;\n public readonly bankAccounts: BankAccountOperations;\n public readonly transports: TransportOperations;\n public readonly legalEntities: LegalEntityOperations;\n\n constructor(config: PeppolConfig) {\n if (!config.apiKey) {\n throw new PeppolError(\n 'API key is required. Sign up at https://console.getpeppr.dev to get your sandbox key.'\n );\n }\n\n this.adapter = new GetpepprAdapter(config);\n this.invoices = new InvoiceOperations(this.adapter);\n this.creditNotes = new CreditNoteOperations(this.adapter);\n this.directory = new DirectoryOperations(this.adapter);\n this.events = new EventOperations(this.adapter);\n this.contacts = new ContactOperations(this.adapter);\n this.bankAccounts = new BankAccountOperations(this.adapter);\n this.transports = new TransportOperations(this.adapter);\n this.legalEntities = new LegalEntityOperations(this.adapter);\n }\n\n /**\n * Validate an invoice without sending it.\n * Useful for pre-flight checks in your UI.\n */\n validate(input: InvoiceInput): ValidationResult {\n return validateInvoice(input);\n }\n\n /**\n * Generate UBL XML without sending.\n * Useful for debugging or manual submission.\n */\n toXml(input: InvoiceInput): string {\n const validation = validateInvoice(input);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Invoice validation failed: ${validation.errors.map((e) => e.message).join(\"; \")}`,\n validation\n );\n }\n if (input.isCreditNote) {\n return buildCreditNoteXml(input as unknown as CreditNoteInput);\n }\n return buildInvoiceXml(input);\n }\n}\n\n/** @internal — exported for testing only; not part of the public SDK surface. */\nexport async function* paginate<T>(\n fetchPage: (offset: number, limit: number) => Promise<PaginatedResult<T>>,\n options?: { limit?: number },\n): AsyncGenerator<T> {\n const pageSize = options?.limit ?? 25;\n let offset = 0;\n\n while (true) {\n const page = await fetchPage(offset, pageSize);\n if (page.data.length === 0) break; // safety: empty page (even with hasMore=true) ends iteration\n for (const item of page.data) {\n yield item;\n }\n if (!page.meta.hasMore) break;\n offset += page.data.length; // FIX (GPR-414 #6): was += pageSize, which silently skipped records on partial pages\n }\n}\n\nclass InvoiceOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Create a draft invoice without sending it.\n * Validates input client-side, then creates the invoice via the gateway.\n * Use `sendById()` to send the draft when ready.\n *\n * @example\n * ```ts\n * const draft = await peppol.invoices.create({ number: \"INV-001\", to, lines });\n * // Later, when ready:\n * await peppol.invoices.sendById(draft.id);\n * ```\n */\n async create(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n const validation = validateInvoice(input);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Invoice validation failed:\\n${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (${e.suggestion})` : \"\"}`).join(\"\\n\")}`,\n validation\n );\n }\n\n const result = await this.adapter.createInvoice(input, options);\n\n if (validation.warnings.length > 0) {\n result.warnings = validation.warnings;\n }\n\n return result;\n }\n\n /**\n * Send an existing draft invoice by ID.\n * The invoice must have been previously created with `create()`.\n *\n * @example\n * ```ts\n * await peppol.invoices.sendById(\"inv-1\");\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support draft sending\n */\n async sendById(id: string): Promise<void> {\n return this.adapter.sendInvoiceById(id);\n }\n\n /**\n * Send an invoice via Peppol.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.send({\n * number: \"INV-001\",\n * from: { name: \"My Company\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * to: { name: \"Client Co\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * lines: [\n * { description: \"Consulting\", quantity: 10, unitPrice: 150, vatRate: 21 }\n * ]\n * });\n * ```\n */\n async send(input: InvoiceInput, options?: InvoiceOperationOptions): Promise<SendResult> {\n // Client-side validation for fast feedback\n const validation = validateInvoice(input);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Invoice validation failed:\\n${validation.errors.map((e) => ` - ${e.field}: ${e.message}${e.suggestion ? ` (${e.suggestion})` : \"\"}`).join(\"\\n\")}`,\n validation\n );\n }\n\n // Send structured JSON — gateway handles UBL generation\n const result = await this.adapter.sendInvoice(input, options);\n\n if (validation.warnings.length > 0) {\n result.warnings = validation.warnings;\n }\n\n return result;\n }\n\n /** List invoices with pagination, filtering, and proper metadata */\n async list(options?: ListInvoicesOptions): Promise<PaginatedResult<InvoiceSummary>> {\n return this.adapter.listInvoices(options);\n }\n\n /**\n * Async iterator over all invoices, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const invoice of peppol.invoices.listAll()) {\n * console.log(invoice.id, invoice.status);\n * }\n * ```\n */\n listAll(options?: Omit<ListInvoicesOptions, \"offset\">): AsyncIterable<InvoiceSummary> {\n return paginate(\n (offset, limit) => this.adapter.listInvoices({ ...options, offset, limit }),\n options,\n );\n }\n\n /** Get the status of a sent invoice */\n async getStatus(documentId: string): Promise<SendResult> {\n return this.adapter.getStatus(documentId);\n }\n\n /**\n * Export an invoice in a specific format (e.g., PDF, UBL XML).\n * Returns raw binary data as an ArrayBuffer.\n *\n * @example\n * ```ts\n * const pdf = await peppol.invoices.getAs(\"inv-123\", \"pdf\");\n * fs.writeFileSync(\"invoice.pdf\", Buffer.from(pdf));\n * ```\n */\n async getAs(id: string, format: DocumentFormat): Promise<ArrayBuffer> {\n return this.adapter.getInvoiceAs(id, format);\n }\n\n /**\n * Validate an invoice server-side using the getpeppr gateway's offline SDK-backed checks.\n * The gateway runs SDK validation, verifies UBL XML generation, and evaluates offline\n * Peppol business rules without sending the invoice to Storecove.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.validateServer({\n * number: \"INV-001\",\n * to: { name: \"Acme\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * lines: [{ description: \"Item\", quantity: 1, unitPrice: 100, vatRate: 21 }]\n * });\n * console.log(result.valid, result.schematron.errors);\n * ```\n * Validation findings return a structured result with valid=false. Transport, auth,\n * malformed request, and unexpected gateway failures still throw PeppolApiError.\n */\n async validateServer(input: InvoiceInput): Promise<ServerValidationResult> {\n return this.adapter.validateDocumentServer(input);\n }\n\n /**\n * Import an invoice from a file (XML, PDF, JSON).\n * The file is base64-encoded and sent to the gateway, which forwards it\n * as multipart/form-data to the provider's import endpoint.\n *\n * @example\n * ```ts\n * const xmlBytes = fs.readFileSync(\"invoice.xml\");\n * const result = await peppol.invoices.importFile({\n * file: xmlBytes,\n * filename: \"invoice.xml\",\n * });\n * console.log(result.id, result.status);\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support file import\n */\n async importFile(options: ImportInvoiceOptions): Promise<SendResult> {\n return this.adapter.importInvoice(options);\n }\n\n /**\n * Acknowledge a received invoice.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.acknowledge(\"inv-123\");\n * console.log(result.status); // \"accepted\"\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support acknowledgement\n */\n async acknowledge(id: string): Promise<SendResult> {\n return this.adapter.acknowledgeInvoice(id);\n }\n\n /**\n * Update an existing invoice (draft only).\n * Only include the fields you want to change — partial updates are supported.\n *\n * @example\n * ```ts\n * const updated = await peppol.invoices.update(\"inv-123\", {\n * dueDate: \"2026-04-01\",\n * lines: [\n * { id: \"line-1\", quantity: 5 },\n * { id: \"line-2\", _destroy: true },\n * ],\n * });\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support invoice updates\n */\n async update(id: string, input: InvoiceUpdateInput): Promise<SendResult> {\n return this.adapter.updateInvoice(id, input);\n }\n\n /**\n * Delete an invoice.\n *\n * @example\n * ```ts\n * const deleted = await peppol.invoices.delete(\"inv-123\");\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support invoice deletion\n */\n async delete(id: string): Promise<SendResult> {\n return this.adapter.deleteInvoice(id);\n }\n\n /**\n * Transition an invoice to a new state.\n * The gateway validates the state machine — invalid transitions return an error.\n *\n * @example\n * ```ts\n * await peppol.invoices.markAs(\"inv-123\", \"accepted\");\n * await peppol.invoices.markAs(\"inv-123\", \"paid\", {\n * commit: \"with_mail\",\n * reason: \"Payment received\",\n * });\n * ```\n * @throws {PeppolApiError} 501 if the gateway provider does not support state transitions\n */\n async markAs(id: string, state: MarkAsState, options?: MarkAsOptions): Promise<SendResult> {\n return this.adapter.markInvoiceAs(id, state, options);\n }\n\n /**\n * Send multiple invoices in parallel with controlled concurrency.\n * Each invoice is validated and sent individually — failures don't affect other invoices\n * unless `stopOnError: true` is set.\n *\n * The SDK's built-in retry logic (including 429 Retry-After) provides automatic\n * rate-limit handling at the request level.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.sendBatch([invoice1, invoice2, invoice3], {\n * concurrency: 3,\n * });\n * console.log(`${result.succeeded.length} sent, ${result.failed.length} failed`);\n * ```\n */\n async sendBatch(\n inputs: InvoiceInput[],\n options?: BatchSendOptions,\n ): Promise<BatchSendResult> {\n const concurrency = options?.concurrency ?? 5;\n const stopOnError = options?.stopOnError ?? false;\n\n const succeeded: BatchSendResult[\"succeeded\"] = [];\n const failed: BatchSendResult[\"failed\"] = [];\n let stopped = false;\n\n // Process in chunks of `concurrency` size\n for (let i = 0; i < inputs.length; i += concurrency) {\n if (stopped) break;\n\n const chunk = inputs.slice(i, i + concurrency);\n const promises = chunk.map(async (input, j) => {\n const index = i + j;\n if (stopped) return;\n try {\n const result = await this.send(input);\n succeeded.push({ index, result });\n } catch (error) {\n failed.push({ index, input, error: error as Error });\n if (stopOnError) {\n stopped = true;\n }\n }\n });\n\n await Promise.all(promises);\n }\n\n return { succeeded, failed, total: inputs.length };\n }\n\n /**\n * Poll until an invoice reaches a target status.\n *\n * @example\n * ```ts\n * const result = await peppol.invoices.waitFor(id, \"accepted\", { timeout: 60000 });\n * ```\n */\n async waitFor(\n documentId: string,\n targetStatus: DocumentStatus | DocumentStatus[],\n options?: WaitForOptions,\n ): Promise<SendResult> {\n const timeout = options?.timeout ?? 120_000;\n const interval = options?.interval ?? 5_000;\n const targets = Array.isArray(targetStatus) ? targetStatus : [targetStatus];\n const terminalFailures: DocumentStatus[] = [\"failed\", \"rejected\"];\n const startTime = Date.now();\n\n while (true) {\n const result = await this.getStatus(documentId);\n\n if (targets.includes(result.status)) {\n return result;\n }\n\n if (terminalFailures.includes(result.status)) {\n throw new PeppolError(\n `Document ${documentId} reached terminal status \"${result.status}\" while waiting for \"${targets.join('\" or \"')}\"`\n );\n }\n\n if (Date.now() - startTime >= timeout) {\n throw new PeppolError(\n `Timed out waiting for document ${documentId} to reach status \"${targets.join('\" or \"')}\" (last: \"${result.status}\")`\n );\n }\n\n await sleep(interval);\n }\n }\n}\n\n/** @deprecated Use peppol.invoices.send() with isCreditNote: true instead */\nclass CreditNoteOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Send a credit note via Peppol.\n * @deprecated Use peppol.invoices.send({ ...input, isCreditNote: true }) instead.\n */\n async send(input: CreditNoteInput): Promise<SendResult> {\n // Convert to InvoiceInput with isCreditNote flag and delegate to sendInvoice\n const invoiceInput: InvoiceInput = {\n ...input,\n isCreditNote: true,\n invoiceReference: input.invoiceReference,\n };\n\n const validation = validateInvoice(invoiceInput);\n if (!validation.valid) {\n throw new PeppolValidationError(\n `Credit note validation failed:\\n${validation.errors.map((e) => ` - ${e.field}: ${e.message}`).join(\"\\n\")}`,\n validation\n );\n }\n\n // Route through sendInvoice — the provider has no separate credit-notes endpoint\n return this.adapter.sendInvoice(invoiceInput);\n }\n}\n\n// ─── Directory Operations ───────────────────────────────────\n\nclass DirectoryOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Look up a Peppol participant in the directory.\n *\n * @example\n * ```ts\n * const entry = await peppol.directory.lookup(\"0208:0685660237\");\n * console.log(entry.name, entry.capabilities);\n * ```\n */\n async lookup(peppolId: PeppolId): Promise<DirectoryEntry> {\n const colonIndex = peppolId.indexOf(\":\");\n if (colonIndex === -1) {\n throw new PeppolError(\n 'Invalid Peppol ID format. Expected \"scheme:id\" (e.g., \"0208:0685660237\")',\n );\n }\n const scheme = peppolId.slice(0, colonIndex);\n const id = peppolId.slice(colonIndex + 1);\n return this.adapter.lookupDirectory(scheme, id);\n }\n\n /**\n * Search the Peppol Directory for participants.\n *\n * @example\n * ```ts\n * const result = await peppol.directory.search({ name: \"Acme\", country: \"BE\" });\n * console.log(result.data); // DirectoryEntry[]\n * console.log(result.meta.totalCount);\n * ```\n */\n async search(options: DirectorySearchOptions): Promise<DirectorySearchResult> {\n if (!options.name && !options.country && !options.vatNumber) {\n throw new PeppolError(\"At least one search criterion is required (name, country, or vatNumber)\");\n }\n if (options.name && options.name.length < 3) {\n throw new PeppolError(\"Search name must be at least 3 characters\");\n }\n if (!this.adapter.searchDirectory) {\n throw new PeppolError(\"Directory search is not supported by this backend adapter\");\n }\n\n const params: Record<string, string> = {};\n if (options.name) params.name = options.name;\n if (options.country) params.country = options.country;\n if (options.vatNumber) params.vatNumber = options.vatNumber;\n if (options.limit !== undefined) params.limit = String(options.limit);\n if (options.offset !== undefined) params.offset = String(options.offset);\n\n return this.adapter.searchDirectory(params);\n }\n\n /**\n * Search the Peppol Directory by VAT number.\n * Convenience method — equivalent to `search({ vatNumber })`.\n *\n * @example\n * ```ts\n * const result = await peppol.directory.searchByVat(\"BE0685660237\");\n * ```\n */\n async searchByVat(vatNumber: string): Promise<DirectorySearchResult> {\n return this.search({ vatNumber });\n }\n}\n\n// ─── Event Operations ────────────────────────────────────────\n\nclass EventOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List events with optional filtering and pagination.\n *\n * @example\n * ```ts\n * const result = await peppol.events.list({ limit: 10 });\n * console.log(result.data, result.meta);\n *\n * // Filter by invoice\n * const invoiceEvents = await peppol.events.list({ invoiceId: \"inv-123\" });\n * ```\n */\n async list(options?: ListEventsOptions): Promise<PaginatedResult<EventEntry>> {\n return this.adapter.listEvents(options);\n }\n\n /**\n * Async iterator over all events, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const event of peppol.events.listAll({ invoiceId: \"inv-123\" })) {\n * console.log(event.name, event.createdAt);\n * }\n * ```\n */\n listAll(options?: Omit<ListEventsOptions, \"offset\">): AsyncIterable<EventEntry> {\n return paginate(\n (offset, limit) => this.adapter.listEvents({ ...options, offset, limit }),\n options,\n );\n }\n}\n\n// ─── Contact Operations ─────────────────────────────────────\n\nclass ContactOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List contacts with optional filtering and pagination.\n *\n * @example\n * ```ts\n * const result = await peppol.contacts.list({ limit: 10, isClient: true });\n * console.log(result.data, result.meta);\n * ```\n */\n async list(options?: ListContactsOptions): Promise<PaginatedResult<Contact>> {\n return this.adapter.listContacts(options);\n }\n\n /**\n * Get a single contact by ID.\n *\n * @example\n * ```ts\n * const contact = await peppol.contacts.get(\"123\");\n * console.log(contact.name, contact.peppolId);\n * ```\n */\n async get(id: string): Promise<Contact> {\n return this.adapter.getContact(id);\n }\n\n /**\n * Create a new contact.\n *\n * @example\n * ```ts\n * const contact = await peppol.contacts.create({\n * name: \"ACMEDIA\",\n * peppolId: \"0208:0685660237\",\n * country: \"BE\",\n * isClient: true,\n * });\n * ```\n */\n async create(input: ContactInput): Promise<Contact> {\n return this.adapter.createContact(input);\n }\n\n /**\n * Update an existing contact.\n *\n * @example\n * ```ts\n * const updated = await peppol.contacts.update(\"123\", { email: \"new@acme.com\" });\n * ```\n */\n async update(id: string, input: Partial<ContactInput>): Promise<Contact> {\n return this.adapter.updateContact(id, input);\n }\n\n /**\n * Delete a contact.\n *\n * @example\n * ```ts\n * await peppol.contacts.delete(\"123\");\n * ```\n */\n async delete(id: string): Promise<void> {\n return this.adapter.deleteContact(id);\n }\n\n /**\n * Async iterator over all contacts, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const contact of peppol.contacts.listAll({ isClient: true })) {\n * console.log(contact.name, contact.peppolId);\n * }\n * ```\n */\n listAll(options?: Omit<ListContactsOptions, \"offset\">): AsyncIterable<Contact> {\n return paginate(\n (offset, limit) => this.adapter.listContacts({ ...options, offset, limit }),\n options,\n );\n }\n}\n\nclass LegalEntityOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * Create a sub-tenant Legal Entity for one of your customers.\n *\n * Idempotent on `externalId`: repeated calls with the same `externalId` return\n * the existing entity (HTTP 200) instead of creating a duplicate. Transient 5xx\n * failures are NOT auto-retried unless you pass `options.idempotencyKey`.\n *\n * @example\n * ```ts\n * const le = await peppol.legalEntities.create({\n * externalId: \"tenant-42\",\n * companyName: \"Acme Health AB\",\n * country: \"SE\",\n * address: { line1: \"Storgatan 1\", city: \"Stockholm\", zip: \"11122\" },\n * identifier: { scheme: \"0007\", value: \"5560000001\" },\n * }, { idempotencyKey: \"tenant-42-create\" });\n * ```\n */\n async create(input: LegalEntityInput, options?: LegalEntityRequestOptions): Promise<LegalEntity> {\n return this.adapter.createLegalEntity(input, options);\n }\n\n /**\n * Fetch a single sub-tenant Legal Entity by id. For production entities the\n * `status` reflects the attestation lifecycle (awaiting_authz → attested → active).\n */\n async get(id: string): Promise<LegalEntity> {\n return this.adapter.getLegalEntity(id);\n }\n\n /** List your sub-tenant Legal Entities, newest first. */\n async list(options?: ListLegalEntitiesOptions): Promise<PaginatedResult<LegalEntity>> {\n return this.adapter.listLegalEntities(options);\n }\n\n /**\n * Async iterator over all sub-tenant Legal Entities, handling pagination.\n *\n * @example\n * ```ts\n * for await (const le of peppol.legalEntities.listAll()) console.log(le.id, le.status);\n * ```\n */\n listAll(options?: Omit<ListLegalEntitiesOptions, \"offset\">): AsyncIterable<LegalEntity> {\n return paginate(\n (offset, limit) => this.adapter.listLegalEntities({ ...options, offset, limit }),\n options,\n );\n }\n\n /** Archive (soft-delete) a sub-tenant Legal Entity. The id stays resolvable for audit. */\n async archive(id: string): Promise<ArchiveLegalEntityResult> {\n return this.adapter.archiveLegalEntity(id);\n }\n\n /**\n * Request a sub-tenant attestation (production only). Emails the co-branded\n * confirmation link to the sub-tenant contact and returns the pending status.\n *\n * Transient failures are NOT auto-retried unless you pass `options.idempotencyKey`;\n * re-issuing mints a fresh token, so a retried call is safe.\n *\n * @example\n * ```ts\n * await peppol.legalEntities.requestAttestation(le.id, { contactEmail: \"owner@acme.example\" });\n * ```\n */\n async requestAttestation(id: string, input: AttestationInput, options?: LegalEntityRequestOptions): Promise<AttestationResult> {\n return this.adapter.requestLegalEntityAttestation(id, input, options);\n }\n}\n\n// ─── Bank Account Operations ─────────────────────────────────\n\nclass BankAccountOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List bank accounts with optional pagination.\n *\n * @example\n * ```ts\n * const result = await peppol.bankAccounts.list({ limit: 10 });\n * console.log(result.data, result.meta);\n * ```\n */\n async list(options?: ListBankAccountsOptions): Promise<PaginatedResult<BankAccount>> {\n return this.adapter.listBankAccounts(options);\n }\n\n /**\n * Get a single bank account by ID.\n *\n * @example\n * ```ts\n * const account = await peppol.bankAccounts.get(\"123\");\n * console.log(account.name, account.iban);\n * ```\n */\n async get(id: string): Promise<BankAccount> {\n return this.adapter.getBankAccount(id);\n }\n\n /**\n * Create a new bank account.\n *\n * @example\n * ```ts\n * const account = await peppol.bankAccounts.create({\n * name: \"Main Account\",\n * iban: \"BE68539007547034\",\n * bic: \"BBRUBEBB\",\n * country: \"BE\",\n * });\n * ```\n */\n async create(input: BankAccountInput): Promise<BankAccount> {\n return this.adapter.createBankAccount(input);\n }\n\n /**\n * Update an existing bank account.\n *\n * @example\n * ```ts\n * const updated = await peppol.bankAccounts.update(\"123\", { name: \"Updated Name\" });\n * ```\n */\n async update(id: string, input: Partial<BankAccountInput>): Promise<BankAccount> {\n return this.adapter.updateBankAccount(id, input);\n }\n\n /**\n * Delete a bank account.\n *\n * @example\n * ```ts\n * await peppol.bankAccounts.delete(\"123\");\n * ```\n */\n async delete(id: string): Promise<void> {\n return this.adapter.deleteBankAccount(id);\n }\n\n /**\n * Async iterator over all bank accounts, automatically handling pagination.\n *\n * @example\n * ```ts\n * for await (const account of peppol.bankAccounts.listAll()) {\n * console.log(account.name, account.iban);\n * }\n * ```\n */\n listAll(options?: Omit<ListBankAccountsOptions, \"offset\">): AsyncIterable<BankAccount> {\n return paginate(\n (offset, limit) => this.adapter.listBankAccounts({ ...options, offset, limit }),\n options,\n );\n }\n}\n\n// ─── Transport Operations ────────────────────────────────────\n\nclass TransportOperations {\n constructor(private adapter: BackendAdapter) {}\n\n /**\n * List all available transport types in the network.\n * Returns global transport types (not account-scoped).\n *\n * @example\n * ```ts\n * const types = await peppol.transports.listTypes();\n * console.log(types); // [{ code: \"peppol\", name: \"Peppol BIS 3.0\" }, ...]\n * ```\n */\n async listTypes(): Promise<TransportType[]> {\n return this.adapter.listTransportTypes();\n }\n\n /**\n * List configured transports for this account.\n *\n * @example\n * ```ts\n * const transports = await peppol.transports.list();\n * console.log(transports); // [{ id: \"t-1\", transportTypeCode: \"peppol\", name: \"...\" }, ...]\n * ```\n */\n async list(): Promise<Transport[]> {\n return this.adapter.listTransports();\n }\n\n /**\n * Get a single transport by code.\n *\n * @example\n * ```ts\n * const transport = await peppol.transports.get(\"peppol\");\n * ```\n */\n async get(code: string): Promise<Transport> {\n return this.adapter.getTransport(code);\n }\n\n /**\n * Create a new transport.\n *\n * @example\n * ```ts\n * const transport = await peppol.transports.create({\n * transportTypeCode: \"peppol\",\n * email: \"billing@acme.com\",\n * });\n * ```\n */\n async create(input: TransportInput): Promise<Transport> {\n return this.adapter.createTransport(input);\n }\n\n /**\n * Update an existing transport.\n *\n * @example\n * ```ts\n * const transport = await peppol.transports.update(\"peppol\", { email: \"new@acme.com\" });\n * ```\n */\n async update(code: string, input: TransportUpdateInput): Promise<Transport> {\n return this.adapter.updateTransport(code, input);\n }\n\n /**\n * Delete a transport.\n *\n * @example\n * ```ts\n * await peppol.transports.delete(\"peppol\");\n * ```\n */\n async delete(code: string): Promise<void> {\n return this.adapter.deleteTransport(code);\n }\n}\n\n// ─── Webhook Helper ─────────────────────────────────────────\n\n/** Default tolerance for webhook timestamp verification (5 minutes) */\nconst DEFAULT_TOLERANCE_SECONDS = 300;\n\n/**\n * Parse and verify a webhook payload from getpeppr.\n *\n * getpeppr signs webhooks with HMAC-SHA256. The signature header format is:\n * `Getpeppr-Signature: t={timestamp},s={hmac_sha256_hex}`\n *\n * The signed payload is: `{timestamp}.{raw_json_body}`\n *\n * @example\n * ```ts\n * app.post(\"/webhooks/peppol\", (req, res) => {\n * try {\n * const event = await Peppol.webhooks.constructEvent(\n * req.body, // raw body string\n * req.headers[\"getpeppr-signature\"], // signature header\n * \"whsec_your_webhook_secret\", // your webhook secret\n * );\n * switch (event.type) {\n * case \"invoice.received\":\n * console.log(\"New invoice from:\", event.data.senderId);\n * break;\n * }\n * res.sendStatus(200);\n * } catch (err) {\n * res.status(400).send(\"Webhook verification failed\");\n * }\n * });\n * ```\n */\nexport const webhooks = {\n /**\n * Parse a webhook payload without signature verification.\n * Use `constructEvent()` for verified parsing in production.\n */\n parse(payload: unknown): WebhookEvent {\n return payload as WebhookEvent;\n },\n\n /**\n * Verify and parse a webhook payload using HMAC-SHA256 signature.\n * Throws `PeppolError` if verification fails.\n *\n * @param rawBody — The raw request body string (NOT parsed JSON)\n * @param signatureHeader — The `Getpeppr-Signature` header value\n * @param secret — Your webhook secret from getpeppr\n * @param toleranceSeconds — Max age of the webhook in seconds (default: 300 = 5 min)\n */\n async constructEvent(\n rawBody: string,\n signatureHeader: string,\n secret: string,\n toleranceSeconds?: number,\n ): Promise<WebhookEvent> {\n if (!rawBody) {\n throw new PeppolError(\"Webhook error: missing request body\");\n }\n if (!signatureHeader) {\n throw new PeppolError(\"Webhook error: missing Getpeppr-Signature header\");\n }\n if (!secret) {\n throw new PeppolError(\"Webhook error: missing webhook secret\");\n }\n\n // Parse header: t={timestamp},s={signature}\n const match = signatureHeader.match(/t=([^,]+),s=(.+)/);\n if (!match) {\n throw new PeppolError(\n \"Webhook error: invalid signature header format. Expected 't={timestamp},s={signature}'\"\n );\n }\n\n const [, timestampStr, receivedSignature] = match;\n const timestamp = Number(timestampStr);\n\n if (!Number.isFinite(timestamp)) {\n throw new PeppolError(\"Webhook error: invalid timestamp in signature header\");\n }\n\n // Check timestamp tolerance (prevent replay attacks)\n const tolerance = toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - timestamp) > tolerance) {\n throw new PeppolError(\n `Webhook error: timestamp too old or too new (received: ${timestamp}, now: ${now}, tolerance: ${tolerance}s)`\n );\n }\n\n // Compute expected signature: HMAC-SHA256(secret, \"{timestamp}.{rawBody}\")\n const signedPayload = `${timestampStr}.${rawBody}`;\n const expectedSignature = await computeHmacSha256(secret, signedPayload);\n\n // Constant-time comparison to prevent timing attacks\n if (!timingSafeEqual(expectedSignature, receivedSignature)) {\n throw new PeppolError(\"Webhook error: signature verification failed\");\n }\n\n // Parse and return the event\n try {\n const parsed = typeof rawBody === \"string\" ? JSON.parse(rawBody) : rawBody;\n return parsed as WebhookEvent;\n } catch {\n throw new PeppolError(\"Webhook error: invalid JSON payload\");\n }\n },\n};\n\n/**\n * Compute HMAC-SHA256 hex digest.\n * Uses Web Crypto API (works in Node.js 18+, Deno, Bun, browsers).\n */\nasync function computeHmacSha256(secret: string, message: string): Promise<string> {\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const signature = await crypto.subtle.sign(\"HMAC\", key, encoder.encode(message));\n return Array.from(new Uint8Array(signature))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n const len = Math.max(a.length, b.length);\n let result = a.length ^ b.length; // non-zero if lengths differ\n for (let i = 0; i < len; i++) {\n result |= (a.charCodeAt(i) || 0) ^ (b.charCodeAt(i) || 0);\n }\n return result === 0;\n}\n","/**\n * Offline Schematron-like Validation\n *\n * Reimplements the top ~25 Peppol BIS 3.0 business rules as pure TypeScript checks.\n * This is NOT a full XSD/XSLT schematron processor — it's a fast, offline validator\n * that catches the most commonly violated rules before the invoice reaches the network.\n *\n * Rules are grouped by category:\n * - BR-xx — Required field rules (EN 16931)\n * - BR-CO-xx — Calculation / cross-field consistency rules\n * - BR-S-xx — Tax category rules\n * - PEPPOL-xx — Peppol BIS 3.0 specific rules\n *\n * Design: each rule is a pure function (InvoiceInput) => SchematronViolation[].\n * No side effects, no XML, no network.\n */\n\nimport type { InvoiceInput, InvoiceLine } from \"../types/invoice.js\";\nimport { resolveUnit, getAllUnits } from \"./code-lists.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface SchematronViolation {\n /** Peppol business rule identifier (e.g., \"BR-02\", \"BR-S-01\") */\n ruleId: string;\n /** Severity: \"error\" blocks sending, \"warning\" is advisory */\n severity: \"error\" | \"warning\";\n /** Human-readable description of the violation */\n message: string;\n /** Relevant field path (e.g., \"lines[0].vatRate\") */\n field?: string;\n}\n\nexport interface SchematronResult {\n /** True if no errors (warnings are non-blocking) */\n valid: boolean;\n /** Blocking violations — invoice would be rejected */\n errors: SchematronViolation[];\n /** Advisory notices — invoice may be accepted but is suboptimal */\n warnings: SchematronViolation[];\n}\n\n// ─── Rule function type ─────────────────────────────────────────────────────────\n\ntype RuleFn = (input: InvoiceInput) => SchematronViolation[];\n\n// ─── Helpers ────────────────────────────────────────────────────────────────────\n\nfunction violation(\n ruleId: string,\n severity: \"error\" | \"warning\",\n message: string,\n field?: string,\n): SchematronViolation {\n return { ruleId, severity, message, field };\n}\n\n/** Build a Set of all known UN/ECE Rec20 unit codes (lazy singleton). */\nlet _knownUnitCodes: Set<string> | undefined;\nfunction getKnownUnitCodes(): Set<string> {\n if (!_knownUnitCodes) {\n _knownUnitCodes = new Set(getAllUnits().map((u) => u.code));\n }\n return _knownUnitCodes;\n}\n\n/** Peppol-allowed VAT category codes (UNCL 5305 subset). */\nconst VALID_VAT_CATEGORIES = new Set([\"S\", \"Z\", \"E\", \"AE\", \"K\", \"G\", \"O\", \"L\", \"M\"]);\n\n/**\n * Compute the net amount for a single invoice line.\n * Formula: (quantity * unitPrice / baseQuantity) + charges - allowances\n */\nfunction computeLineNet(line: InvoiceLine): number {\n const baseQty = line.baseQuantity ?? 1;\n if (baseQty === 0) return NaN; // Will be caught by BR-CO-10\n const baseAmount = (line.quantity * line.unitPrice) / baseQty;\n const chargeTotal = (line.charges ?? []).reduce((sum, c) => sum + c.amount, 0);\n const allowanceTotal = (line.allowances ?? []).reduce((sum, a) => sum + a.amount, 0);\n return baseAmount + chargeTotal - allowanceTotal;\n}\n\n// ─── Required Field Rules (BR-01 to BR-10) ──────────────────────────────────────\n\n/**\n * BR-01: Invoice shall have a Specification identifier.\n * Auto-pass: the gateway always sets \"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\".\n */\n// (no-op — always satisfied)\n\n/**\n * BR-02: An Invoice shall have an Invoice number.\n */\nconst br02: RuleFn = (input) => {\n if (!input.number?.trim()) {\n return [violation(\"BR-02\", \"error\", \"Invoice number is required.\", \"number\")];\n }\n return [];\n};\n\n/**\n * BR-03: An Invoice shall have an Invoice issue date.\n * The SDK defaults to today if omitted, so this is a warning.\n */\nconst br03: RuleFn = (input) => {\n if (!input.date) {\n return [\n violation(\n \"BR-03\",\n \"warning\",\n \"Invoice issue date is not set. The SDK will default to today's date.\",\n \"date\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * BR-04: An Invoice shall have an Invoice currency code.\n * Auto-pass: defaults to EUR.\n */\n// (no-op)\n\n/**\n * BR-05: An Invoice shall have an Invoice type code.\n * Auto-pass: always set (380 for invoice, 381 for credit note).\n */\n// (no-op)\n\n/**\n * BR-06: An Invoice shall have the Seller VAT identifier or tax registration.\n * The `from` field is deprecated — seller is determined by API key.\n * Only warn if `from` IS provided but has no vatNumber.\n */\nconst br06: RuleFn = (input) => {\n if (input.from && !input.from.vatNumber) {\n return [\n violation(\n \"BR-06\",\n \"warning\",\n \"Seller party has no VAT number. The gateway will use the account's VAT registration.\",\n \"from.vatNumber\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * BR-07: An Invoice shall have the Buyer name.\n */\nconst br07: RuleFn = (input) => {\n if (!input.to?.name?.trim()) {\n return [violation(\"BR-07\", \"error\", \"Buyer name is required.\", \"to.name\")];\n }\n return [];\n};\n\n/**\n * BR-08: An Invoice shall have at least one Invoice line.\n */\nconst br08: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) {\n return [violation(\"BR-08\", \"error\", \"Invoice must have at least one line item.\", \"lines\")];\n }\n return [];\n};\n\n/**\n * BR-09: An Invoice shall have the Payment due date or Payment terms.\n */\nconst br09: RuleFn = (input) => {\n if (!input.dueDate && !input.paymentTerms) {\n return [\n violation(\n \"BR-09\",\n \"warning\",\n \"Neither due date nor payment terms specified. At least one is recommended.\",\n \"dueDate\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * BR-10: An Invoice shall have the Buyer reference or Order reference.\n */\nconst br10: RuleFn = (input) => {\n if (!input.buyerReference && !input.orderReference) {\n return [\n violation(\n \"BR-10\",\n \"warning\",\n \"Neither buyerReference nor orderReference specified. Peppol BIS 3.0 requires at least one.\",\n \"buyerReference\",\n ),\n ];\n }\n return [];\n};\n\n// ─── Calculation Rules (BR-CO) ──────────────────────────────────────────────────\n\n/**\n * BR-CO-10: Sum of Invoice line net amounts = sum of (quantity x unit price / base quantity)\n * adjusted by line allowances/charges.\n *\n * Since InvoiceInput has no explicit totals, we verify each line's computation is valid\n * (no NaN, no Infinity, handles baseQuantity correctly).\n */\nconst brCo10: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const net = computeLineNet(line);\n\n if (!Number.isFinite(net)) {\n const baseQty = line.baseQuantity ?? 1;\n const detail =\n baseQty === 0\n ? \"baseQuantity is 0, causing division by zero.\"\n : \"Computed line amount is not a finite number.\";\n violations.push(\n violation(\"BR-CO-10\", \"error\", `Line ${i}: invalid net amount. ${detail}`, `lines[${i}]`),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-CO-13: Invoice total VAT amount = sum of (line net amount x VAT rate / 100) per category.\n *\n * We verify the VAT computation is valid and consistent. Since InvoiceInput has no explicit\n * VAT total field, we check that the computed amount is finite and non-negative.\n */\nconst brCo13: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) return [];\n\n let totalVat = 0;\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const net = computeLineNet(line);\n if (!Number.isFinite(net)) continue; // Already caught by BR-CO-10\n totalVat += net * (line.vatRate / 100);\n }\n\n // Include document-level allowances/charges in VAT\n for (const allowance of input.allowances ?? []) {\n totalVat -= allowance.amount * (allowance.vatRate / 100);\n }\n for (const charge of input.charges ?? []) {\n totalVat += charge.amount * (charge.vatRate / 100);\n }\n\n if (!Number.isFinite(totalVat)) {\n return [\n violation(\n \"BR-CO-13\",\n \"error\",\n \"Computed total VAT amount is not a finite number. Check line amounts and VAT rates.\",\n ),\n ];\n }\n\n if (totalVat < -0.01) {\n return [\n violation(\n \"BR-CO-13\",\n \"warning\",\n `Computed total VAT is negative (${totalVat.toFixed(2)}). This is unusual for an invoice.`,\n ),\n ];\n }\n\n return [];\n};\n\n/**\n * BR-CO-15: Invoice tax inclusive amount = Invoice total amount without VAT + Invoice total VAT amount.\n *\n * We verify the computation produces a finite, non-negative result.\n */\nconst brCo15: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) return [];\n\n let lineTotal = 0;\n let vatTotal = 0;\n\n for (const line of input.lines) {\n const net = computeLineNet(line);\n if (!Number.isFinite(net)) continue;\n lineTotal += net;\n vatTotal += net * (line.vatRate / 100);\n }\n\n // Document-level allowances/charges\n for (const allowance of input.allowances ?? []) {\n lineTotal -= allowance.amount;\n vatTotal -= allowance.amount * (allowance.vatRate / 100);\n }\n for (const charge of input.charges ?? []) {\n lineTotal += charge.amount;\n vatTotal += charge.amount * (charge.vatRate / 100);\n }\n\n const taxInclusive = lineTotal + vatTotal;\n\n if (!Number.isFinite(taxInclusive)) {\n return [\n violation(\n \"BR-CO-15\",\n \"error\",\n \"Computed tax-inclusive amount is not a finite number.\",\n ),\n ];\n }\n\n if (taxInclusive < -0.01) {\n return [\n violation(\n \"BR-CO-15\",\n \"warning\",\n `Computed tax-inclusive amount is negative (${taxInclusive.toFixed(2)}). Consider using a credit note instead.`,\n ),\n ];\n }\n\n return [];\n};\n\n/**\n * BR-CO-16: Amount due for payment = Invoice total amount with VAT - Paid amount + Rounding amount.\n *\n * Verifies payable amount is non-negative when prepaidAmount is used.\n */\nconst brCo16: RuleFn = (input) => {\n if (!input.lines || input.lines.length === 0) return [];\n\n let lineTotal = 0;\n let vatTotal = 0;\n\n for (const line of input.lines) {\n const net = computeLineNet(line);\n if (!Number.isFinite(net)) continue;\n lineTotal += net;\n vatTotal += net * (line.vatRate / 100);\n }\n\n // Document-level allowances/charges\n for (const allowance of input.allowances ?? []) {\n lineTotal -= allowance.amount;\n vatTotal -= allowance.amount * (allowance.vatRate / 100);\n }\n for (const charge of input.charges ?? []) {\n lineTotal += charge.amount;\n vatTotal += charge.amount * (charge.vatRate / 100);\n }\n\n const taxInclusive = lineTotal + vatTotal;\n const prepaid = input.prepaidAmount ?? 0;\n const rounding = input.roundingAmount ?? 0;\n const payable = taxInclusive - prepaid + rounding;\n\n if (!Number.isFinite(payable)) {\n return [\n violation(\n \"BR-CO-16\",\n \"error\",\n \"Computed payable amount is not a finite number.\",\n ),\n ];\n }\n\n if (payable < -0.01) {\n return [\n violation(\n \"BR-CO-16\",\n \"warning\",\n `Computed payable amount is negative (${payable.toFixed(2)}). Prepaid amount (${prepaid}) exceeds the invoice total.`,\n ),\n ];\n }\n\n return [];\n};\n\n// ─── Tax Category Rules (BR-S) ──────────────────────────────────────────────────\n\n/**\n * BR-S-01: An Invoice that contains a line where the VAT category code is \"Standard rate\" (S)\n * shall have the VAT rate greater than zero.\n */\nconst brS01: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const category = line.vatCategory ?? \"S\"; // Default is standard rate\n if (category === \"S\" && (line.vatRate === undefined || line.vatRate <= 0)) {\n violations.push(\n violation(\n \"BR-S-01\",\n \"error\",\n `Line ${i}: standard rate (S) requires vatRate > 0, got ${line.vatRate ?? \"undefined\"}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-S-05: An Invoice that contains a line where the VAT category code is \"Zero rated\" (Z)\n * shall have the VAT rate equal to 0.\n */\nconst brS05: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.vatCategory === \"Z\" && line.vatRate !== 0) {\n violations.push(\n violation(\n \"BR-S-05\",\n \"error\",\n `Line ${i}: zero-rated (Z) requires vatRate = 0, got ${line.vatRate}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-S-06: An Invoice that contains a line where the VAT category code is \"Exempt\" (E)\n * shall have the VAT rate equal to 0.\n */\nconst brS06: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.vatCategory === \"E\" && line.vatRate !== 0) {\n violations.push(\n violation(\n \"BR-S-06\",\n \"error\",\n `Line ${i}: exempt (E) requires vatRate = 0, got ${line.vatRate}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * BR-S-08: An Invoice that contains a line where the VAT category code is \"Reverse charge\" (AE)\n * shall have the VAT rate equal to 0.\n */\nconst brS08: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.vatCategory === \"AE\" && line.vatRate !== 0) {\n violations.push(\n violation(\n \"BR-S-08\",\n \"error\",\n `Line ${i}: reverse charge (AE) requires vatRate = 0, got ${line.vatRate}.`,\n `lines[${i}].vatRate`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n// ─── Peppol-Specific Rules ──────────────────────────────────────────────────────\n\n/**\n * PEPPOL-EN16931-R001: Business process MUST be provided.\n * Auto-pass: the gateway always sets \"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0\".\n */\n// (no-op)\n\n/**\n * PEPPOL-EN16931-R004: A Buyer electronic address SHALL exist.\n */\nconst peppolR004: RuleFn = (input) => {\n if (!input.to?.peppolId) {\n return [\n violation(\n \"PEPPOL-EN16931-R004\",\n \"error\",\n \"Buyer electronic address (peppolId) is required for Peppol delivery.\",\n \"to.peppolId\",\n ),\n ];\n }\n return [];\n};\n\n/**\n * PEPPOL-EN16931-R006: VAT category code MUST follow the Peppol subset of UNCL 5305.\n * Valid codes: S, Z, E, AE, K, G, O, L, M.\n */\nconst peppolR006: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n const cat = line.vatCategory;\n if (cat !== undefined && !VALID_VAT_CATEGORIES.has(cat)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R006\",\n \"error\",\n `Line ${i}: invalid VAT category \"${cat}\". Must be one of: S, Z, E, AE, K, G, O, L, M.`,\n `lines[${i}].vatCategory`,\n ),\n );\n }\n }\n\n // Also check document-level allowances/charges\n for (let i = 0; i < (input.allowances ?? []).length; i++) {\n const cat = input.allowances![i]!.vatCategory;\n if (cat !== undefined && !VALID_VAT_CATEGORIES.has(cat)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R006\",\n \"error\",\n `Allowance ${i}: invalid VAT category \"${cat}\".`,\n `allowances[${i}].vatCategory`,\n ),\n );\n }\n }\n\n for (let i = 0; i < (input.charges ?? []).length; i++) {\n const cat = input.charges![i]!.vatCategory;\n if (cat !== undefined && !VALID_VAT_CATEGORIES.has(cat)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R006\",\n \"error\",\n `Charge ${i}: invalid VAT category \"${cat}\".`,\n `charges[${i}].vatCategory`,\n ),\n );\n }\n }\n\n return violations;\n};\n\n/**\n * PEPPOL-EN16931-R080: Unit of measure MUST be coded using UN/ECE Recommendation 20.\n * Warning-level since unknown codes pass through to the gateway which may accept them.\n */\nconst peppolR080: RuleFn = (input) => {\n const violations: SchematronViolation[] = [];\n if (!input.lines) return violations;\n\n const knownCodes = getKnownUnitCodes();\n\n for (let i = 0; i < input.lines.length; i++) {\n const line = input.lines[i]!;\n if (line.unit) {\n const resolved = resolveUnit(line.unit);\n if (!knownCodes.has(resolved)) {\n violations.push(\n violation(\n \"PEPPOL-EN16931-R080\",\n \"warning\",\n `Line ${i}: unit \"${line.unit}\" (resolved: \"${resolved}\") is not a known UN/ECE Rec20 code. Common codes: EA, HUR, DAY, KGM.`,\n `lines[${i}].unit`,\n ),\n );\n }\n }\n // No unit specified → defaults to \"EA\" which is valid → no violation\n }\n\n return violations;\n};\n\n// ─── Rule Registry ──────────────────────────────────────────────────────────────\n\n/** All active rules in evaluation order. */\nconst ALL_RULES: readonly RuleFn[] = [\n // Required fields (BR)\n br02,\n br03,\n br06,\n br07,\n br08,\n br09,\n br10,\n // Calculations (BR-CO)\n brCo10,\n brCo13,\n brCo15,\n brCo16,\n // Tax categories (BR-S)\n brS01,\n brS05,\n brS06,\n brS08,\n // Peppol-specific\n peppolR004,\n peppolR006,\n peppolR080,\n];\n\n// ─── Main Validation Function ───────────────────────────────────────────────────\n\n/**\n * Validate an InvoiceInput against Peppol BIS 3.0 business rules (offline).\n *\n * Runs ~25 of the most commonly violated schematron rules as pure TypeScript checks.\n * No XML generation, no network calls — instant feedback.\n *\n * @param input - The invoice to validate\n * @returns Validation result with errors (blocking) and warnings (advisory)\n *\n * @example\n * ```ts\n * const result = validateSchematron({\n * number: \"INV-001\",\n * to: { name: \"Acme\", peppolId: \"0208:0685660237\", country: \"BE\" },\n * lines: [{ description: \"Widget\", quantity: 1, unitPrice: 100, vatRate: 21 }],\n * });\n *\n * if (!result.valid) {\n * console.error(\"Validation failed:\", result.errors);\n * }\n * ```\n */\nexport function validateSchematron(input: InvoiceInput): SchematronResult {\n const errors: SchematronViolation[] = [];\n const warnings: SchematronViolation[] = [];\n\n for (const rule of ALL_RULES) {\n const violations = rule(input);\n for (const v of violations) {\n if (v.severity === \"error\") {\n errors.push(v);\n } else {\n warnings.push(v);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import type { Command } from \"commander\";\nimport { readAndValidateInvoiceJson } 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 input = readAndValidateInvoiceJson(file);\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 { exitWithError } from \"../utils/errors.js\";\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 exitWithError(\n `Error: ${filename} already exists. Use --force to overwrite.`,\n );\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 exitWithError(`Error: could not write file — ${resolved}`);\n }\n\n process.stderr.write(`${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 4. Send: getpeppr send ${filename}\n\n ${pc.dim(\"Sandbox note:\")} this template includes VAT. To send it on a sandbox\n account, first register your VAT in Settings \\u2192 Peppol Identity, or set each\n line's \"vatCategory\" to \"O\" (outside the scope of VAT) for a no-VAT test send.\\n`);\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:0685660237\",\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:0685660237\",\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 { readAndValidateInvoiceJson } from \"../utils/file.js\";\nimport { exitWithError } from \"../utils/errors.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 input = readAndValidateInvoiceJson(file);\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 exitWithError(`Error: XML generation failed — ${message}`);\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 { exitWithError } from \"../utils/errors.js\";\nimport {\n lookupParticipant,\n searchParticipants,\n DirectoryError,\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:0685660237)`,\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 exitWithError(\"Provide a Peppol ID or use --name to search.\");\n }\n\n // Validate --country format\n if (options.country) {\n const normalized = options.country.toUpperCase();\n if (!/^[A-Z]{2}$/.test(normalized)) {\n exitWithError(\n `Invalid country code \"${options.country}\". Must be 2 letters (e.g. BE, DE, FR).`,\n );\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 exitWithError(parsed.error);\n }\n\n let result: DirectoryMatch | null;\n\n try {\n result = await lookupParticipant(parsed.scheme, parsed.id);\n } catch (err) {\n if (err instanceof DirectoryError) {\n exitWithError(\n `${pc.red(\"\\u2717\")} Peppol Directory returned an error (HTTP ${err.status ?? \"unknown\"}). Try again later.`,\n );\n }\n exitWithError(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.`,\n );\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 exitWithError(\n `Search name must be at least 3 characters. Got: \"${options.name}\"`,\n );\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 (err) {\n if (err instanceof DirectoryError) {\n exitWithError(\n `${pc.red(\"\\u2717\")} Peppol Directory returned an error (HTTP ${err.status ?? \"unknown\"}). Try again later.`,\n );\n }\n exitWithError(\n `${pc.red(\"\\u2717\")} Could not reach Peppol Directory. Check your internet connection.`,\n );\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// ─── Errors ───────────────────────────────────────\n\nexport class DirectoryError extends Error {\n readonly status?: number;\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"DirectoryError\";\n this.status = status;\n }\n}\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}:${normalizeParticipantIdentifier(scheme, id)}`;\n const url = `${BASE_URL}?participant=${encodeURIComponent(participantParam)}`;\n\n const response = await fetch(url, {\n signal: AbortSignal.timeout(15_000),\n headers: { \"User-Agent\": \"@getpeppr/cli\" },\n });\n if (!response.ok) {\n throw new DirectoryError(\n `Lookup failed: HTTP ${response.status} ${response.statusText}`,\n response.status,\n );\n }\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\nfunction normalizeParticipantIdentifier(scheme: string, id: string): string {\n if (scheme === \"0208\") {\n return id.replace(/^BE(?=(?:0|1)\\d{9}$)/i, \"\");\n }\n\n return id;\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 signal: AbortSignal.timeout(15_000),\n headers: { \"User-Agent\": \"@getpeppr/cli\" },\n });\n if (!response.ok) {\n throw new DirectoryError(\n `Search failed: HTTP ${response.status} ${response.statusText}`,\n response.status,\n );\n }\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","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { Peppol } from \"@getpeppr/sdk\";\n\nimport { exitWithError } from \"../utils/errors.js\";\nimport { resolveApiKey, AuthError } from \"../lib/auth.js\";\nimport { buildPayload, MutexError } from \"../lib/send-payload.js\";\nimport { confirmInteractive } from \"../lib/confirm.js\";\nimport { pollUntilTerminal } from \"../lib/watch.js\";\nimport { formatSendResult } from \"../formatters/send-result.js\";\nimport { runValidation } from \"./validate.js\";\n\ninterface SendFlags {\n prod?: boolean;\n local?: boolean;\n key?: string;\n to?: string;\n country?: string;\n amount?: string;\n currency?: string;\n desc?: string;\n attachment?: boolean;\n watch?: boolean;\n yes?: boolean;\n validate?: boolean; // commander negates --no-validate to validate=false\n json?: boolean;\n quiet?: boolean;\n}\n\nconst API_BASE = \"https://api.getpeppr.dev/v1\";\nconst LOCAL_BASE = \"http://localhost:3001/api/v1\";\nconst DASHBOARD_BASE = \"https://console.getpeppr.dev/invoices\";\n\nexport function registerSendCommand(program: Command): void {\n program\n .command(\"send\")\n .description(\"Send an invoice to the Peppol network via getpeppr API\")\n .argument(\"[file]\", \"optional path to invoice JSON (mutex with --to/--amount/...)\")\n .option(\"--prod\", \"target production (live keys + confirmation)\")\n .option(\"--local\", \"target localhost:3001 dev server\")\n .option(\"--key <key>\", \"override API key — for CI/scripted use only; visible in `ps` and shell history. Prefer GETPEPPR_API_KEY env var.\")\n .option(\"--to <peppol-id>\", \"recipient peppol id (e.g., 9925:BE0314595348)\")\n .option(\"--country <iso>\", \"recipient ISO 3166-1 alpha-2 country override (e.g., BE)\")\n .option(\"--amount <number>\", \"line amount in major currency units (decimal allowed)\")\n .option(\"--currency <iso>\", \"ISO 4217 currency (default EUR)\")\n .option(\"--desc <text>\", \"line description\")\n .option(\"--attachment\", \"attach the test PDF\")\n .option(\"--watch\", \"poll status until delivered (60s timeout)\")\n .option(\"-y, --yes\", \"skip --prod confirmation prompt\")\n .option(\"--no-validate\", \"skip pre-validation locally\")\n .option(\"--json\", \"output JSON\")\n .option(\"--quiet\", \"exit code only, no output\")\n .action(async (file: string | undefined, flags: SendFlags) => {\n // 1. Resolve auth\n let auth;\n try {\n auth = resolveApiKey({\n flagKey: flags.key,\n forceProd: Boolean(flags.prod),\n forceLocal: Boolean(flags.local),\n });\n } catch (e) {\n if (e instanceof AuthError) {\n exitWithError(e.message);\n return;\n }\n throw e;\n }\n\n // 2. Build payload\n const overrides = {\n to: flags.to,\n country: flags.country,\n amount: flags.amount != null ? Number(flags.amount) : undefined,\n currency: flags.currency,\n description: flags.desc,\n attachment: flags.attachment,\n };\n let payload;\n try {\n payload = buildPayload({ file, overrides });\n } catch (e) {\n if (e instanceof MutexError) {\n exitWithError(e.message);\n return;\n }\n if (e instanceof Error) {\n exitWithError(e.message);\n return;\n }\n throw e;\n }\n\n // 3. Pre-validate (unless --no-validate)\n if (flags.validate !== false) {\n const result = runValidation(payload);\n if (!result.valid) {\n process.stderr.write(\n `${pc.red(\"✗\")} Pre-validation failed (${result.totalErrors} errors). Use --no-validate to skip.\\n`,\n );\n process.exit(2);\n }\n }\n\n // 4. --prod confirmation\n if (flags.prod && !flags.yes) {\n const confirmed = await confirmInteractive({\n prompt: pc.yellow(\"⚠ About to send a REAL invoice on the Peppol network. Continue?\"),\n defaultYes: false,\n });\n if (!confirmed) {\n if (!flags.quiet) process.stderr.write(\"Cancelled.\\n\");\n process.exit(0);\n }\n }\n\n // 5. Build SDK client\n const baseUrl = flags.local ? LOCAL_BASE : API_BASE;\n const client = new Peppol({ apiKey: auth.apiKey, baseUrl });\n\n // 6. Send\n let result;\n try {\n result = await client.invoices.send(payload);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n process.stderr.write(`${pc.red(\"✗\")} ${msg}\\n`);\n process.exit(1);\n }\n\n const dashboardUrl = `${DASHBOARD_BASE}/${result.id}`;\n\n // 7. --watch\n let finalStatus: string = result.status;\n let timedOut = false;\n if (flags.watch) {\n const onTransition = (s: string) => {\n if (!flags.quiet && !flags.json) {\n process.stderr.write(` ${pc.cyan(\"→\")} ${s}\\n`);\n }\n };\n try {\n const w = await pollUntilTerminal(client, result.id, {\n intervalMs: 2000,\n timeoutMs: 60_000,\n onTransition,\n });\n finalStatus = w.finalStatus;\n timedOut = w.timedOut;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n process.stderr.write(`${pc.yellow(\"⚠\")} Watch error: ${msg}\\n`);\n }\n if (timedOut) {\n process.stderr.write(\n `${pc.yellow(\"⚠\")} Timeout — invoice was sent but delivery not confirmed in 60s.\\n`,\n );\n }\n }\n\n // 8. Output\n const mode = flags.quiet ? \"quiet\" : flags.json ? \"json\" : \"formatted\";\n const output = formatSendResult(\n {\n id: result.id,\n number: payload.number,\n status: finalStatus,\n warnings: result.warnings,\n dashboardUrl,\n },\n mode,\n );\n if (output) process.stdout.write(output + \"\\n\");\n\n // 9. Exit code\n if (finalStatus === \"rejected\" || finalStatus === \"failed\") {\n process.exit(1);\n }\n process.exit(0);\n });\n}\n","import {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n statSync,\n writeFileSync,\n renameSync,\n} from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport interface Credentials {\n sandbox?: string;\n live?: string;\n}\n\nexport function getCredentialsPath(): string {\n if (platform() === \"win32\") {\n const appdata = process.env.APPDATA ?? join(homedir(), \"AppData\", \"Roaming\");\n return join(appdata, \"getpeppr\", \"credentials.json\");\n }\n // XDG-compliant default; respects $XDG_CONFIG_HOME\n const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\");\n return join(xdg, \"getpeppr\", \"credentials.json\");\n}\n\nexport function readCredentials(): Credentials | null {\n const path = getCredentialsPath();\n if (!existsSync(path)) return null;\n\n // Permission check (POSIX only)\n if (platform() !== \"win32\") {\n const stats = statSync(path);\n const mode = stats.mode & 0o777;\n if (mode !== 0o600) {\n process.stderr.write(\n `⚠ Config file mode was ${mode.toString(8)}; restoring to 600.\\n`,\n );\n chmodSync(path, 0o600);\n }\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf-8\");\n } catch {\n process.stderr.write(`⚠ Could not read config file: ${path}\\n`);\n return null;\n }\n\n try {\n const data = JSON.parse(raw) as Credentials;\n return data;\n } catch {\n process.stderr.write(`⚠ Malformed JSON in config file: ${path}\\n`);\n return null;\n }\n}\n\nexport function writeCredentials(creds: Credentials): void {\n const path = getCredentialsPath();\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n\n // Atomic write: tmp file + rename, with mode 600 (POSIX only)\n const tmpPath = `${path}.tmp`;\n const data = JSON.stringify(creds, null, 2) + \"\\n\";\n\n // Defensive: clean up any orphan tmp from a previous crashed run.\n try { rmSync(tmpPath, { force: true }); } catch { /* best effort */ }\n\n // flag: \"wx\" fails if tmp exists (eliminates mode retention) + explicit chmod as belt-and-suspenders.\n writeFileSync(tmpPath, data, { mode: 0o600, flag: \"wx\" });\n chmodSync(tmpPath, 0o600);\n\n try {\n renameSync(tmpPath, path);\n } catch (e) {\n try { rmSync(tmpPath, { force: true }); } catch { /* best effort */ }\n throw e;\n }\n}\n\nexport function deleteCredentials(): boolean {\n const path = getCredentialsPath();\n if (!existsSync(path)) return false;\n rmSync(path);\n return true;\n}\n","import { readCredentials } from \"./credentials-store.js\";\n\nexport type Environment = \"sandbox\" | \"live\";\nexport type AuthSource = \"flag\" | \"env\" | \"config\";\n\nexport interface ResolvedAuth {\n apiKey: string;\n source: AuthSource;\n environment: Environment;\n}\n\nexport interface ResolveOptions {\n flagKey?: string;\n forceProd: boolean;\n forceLocal: boolean; // reserved for Task 10 (--local flag); resolveApiKey itself does not use it\n}\n\nexport class AuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\nexport function resolveApiKey(opts: ResolveOptions): ResolvedAuth {\n const env: Environment = opts.forceProd ? \"live\" : \"sandbox\";\n\n // 1. Flag has highest priority\n if (opts.flagKey) {\n return { apiKey: opts.flagKey, source: \"flag\", environment: env };\n }\n\n // 2. Env var\n const envKey = process.env.GETPEPPR_API_KEY;\n if (envKey) {\n return { apiKey: envKey, source: \"env\", environment: env };\n }\n\n // 3. Config file\n const creds = readCredentials();\n if (creds) {\n const key = env === \"live\" ? creds.live : creds.sandbox;\n if (key) {\n return { apiKey: key, source: \"config\", environment: env };\n }\n if (env === \"live\") {\n throw new AuthError(\n `Config has no live API key. Run \\`getpeppr login\\` again with --live, or pass --key.`,\n );\n }\n }\n\n // 4. Nothing found\n throw new AuthError(\n `No API key found. Run \\`getpeppr login\\` or set GETPEPPR_API_KEY.`,\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { InvoiceInput } from \"@getpeppr/sdk\";\nimport { buildDefaultSendPayload, type SendDefaultOverrides } from \"../templates/send-default.js\";\n\nexport class MutexError extends Error {\n constructor() {\n super(\"Cannot combine custom file with override flags. Use one or the other.\");\n this.name = \"MutexError\";\n }\n}\n\nexport interface BuildPayloadOptions {\n file?: string;\n overrides?: SendDefaultOverrides;\n}\n\nfunction hasOverrides(o?: SendDefaultOverrides): boolean {\n if (!o) return false;\n // Use `!= null` for amount (handles 0) and explicit string-emptiness check for `to`.\n // `attachment: false` is the default behaviour, so we treat it as \"no override expressed\".\n // `attachment: true` is the only way to opt into the attachment override.\n return Boolean(\n (o.to != null && o.to !== \"\") ||\n (o.country != null && o.country !== \"\") ||\n o.amount != null ||\n o.currency ||\n o.description ||\n o.attachment === true,\n );\n}\n\nexport function buildPayload(opts: BuildPayloadOptions): InvoiceInput {\n if (opts.file && hasOverrides(opts.overrides)) {\n throw new MutexError();\n }\n\n if (opts.file) {\n const absPath = resolve(opts.file);\n if (!existsSync(absPath)) {\n throw new Error(`Error: file not found — ${absPath}`);\n }\n let raw: string;\n try {\n raw = readFileSync(absPath, \"utf-8\");\n } catch {\n throw new Error(`Error: could not read file — ${absPath}`);\n }\n try {\n return JSON.parse(raw) as InvoiceInput;\n } catch {\n throw new Error(`Error: invalid JSON in file — ${absPath}`);\n }\n }\n\n return buildDefaultSendPayload(opts.overrides);\n}\n","import type { InvoiceInput, PeppolId, CountryCode } from \"@getpeppr/sdk\";\n\n// Minimal valid PDF (Storecove validates content). Canonical source is\n// packages/sdk/scripts/send-test-invoice.ts — if that script's PDF is ever\n// updated, this duplicate must be kept in sync. The scripts/ directory is\n// excluded from SDK tsconfig so cross-package import isn't possible.\nconst MINIMAL_PDF = `%PDF-1.0\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj\nxref\n0 4\n0000000000 65535 f\n0000000009 00000 n\n0000000058 00000 n\n0000000115 00000 n\ntrailer<</Size 4/Root 1 0 R>>\nstartxref\n190\n%%EOF`;\n\nexport const MINIMAL_TEST_PDF_BASE64 = Buffer.from(MINIMAL_PDF).toString(\"base64\");\n\nexport interface SendDefaultOverrides {\n to?: string;\n country?: string;\n amount?: number;\n currency?: string;\n description?: string;\n attachment?: boolean;\n}\n\nconst SCHEME_COUNTRY_DEFAULTS: Record<string, CountryCode> = {\n \"0009\": \"FR\" as CountryCode,\n \"0204\": \"DE\" as CountryCode,\n \"0208\": \"BE\" as CountryCode,\n \"9925\": \"BE\" as CountryCode,\n};\n\nfunction deriveCountryFromPeppolId(peppolId: PeppolId): CountryCode {\n const [scheme, identifier = \"\"] = peppolId.split(\":\");\n const alphaPrefix = identifier.slice(0, 2);\n\n if (/^[A-Za-z]{2}$/.test(alphaPrefix)) {\n return alphaPrefix.toUpperCase() as CountryCode;\n }\n\n return SCHEME_COUNTRY_DEFAULTS[scheme] ?? (\"BE\" as CountryCode);\n}\n\nexport function buildDefaultSendPayload(overrides: SendDefaultOverrides = {}): InvoiceInput {\n const today = new Date();\n const due = new Date(today.getTime() + 30 * 86400000);\n const isoToday = today.toISOString().slice(0, 10);\n const isoDue = due.toISOString().slice(0, 10);\n\n // TODO(Task 10 send command): validate scheme:id format upstream before calling.\n // Cast is safe assuming caller passes valid Peppol ID format (XXXX:YYYYYY).\n const peppolId = (overrides.to ?? \"9925:BE0314595348\") as PeppolId; // SPF Economie BE — accepts test invoices\n const amount = overrides.amount ?? 100;\n const currency = overrides.currency ?? \"EUR\";\n const description = overrides.description ?? \"Test service from getpeppr\";\n\n // Unique invoice number: TEST-{base36 timestamp}-{4-char random hex}.\n // The random suffix guarantees uniqueness even when two calls land within the same millisecond.\n const randomSuffix = Math.floor(Math.random() * 0x10000)\n .toString(16)\n .toUpperCase()\n .padStart(4, \"0\");\n const number = `TEST-${Date.now().toString(36).toUpperCase()}-${randomSuffix}`;\n\n // Best-effort country derivation from Peppol ID. Some Belgian 0208 IDs are bare\n // enterprise numbers (e.g. 0208:0738836782), so fall back to the scheme mapping.\n // CountryCode is `\"BE\" | \"FR\" | ... | (string & {})` so any string is accepted.\n const country = overrides.country != null\n ? overrides.country.toUpperCase() as CountryCode\n : deriveCountryFromPeppolId(peppolId);\n\n const payload: InvoiceInput = {\n number,\n date: isoToday,\n dueDate: isoDue,\n currency,\n to: {\n name: peppolId === \"9925:BE0314595348\" ? \"SPF Economie (TEST)\" : \"Test Recipient\",\n peppolId,\n country,\n street: \"Rue de la Loi 1\",\n city: \"Brussels\",\n postalCode: \"1000\",\n },\n lines: [\n {\n description,\n quantity: 1,\n unitPrice: amount,\n vatRate: 0,\n // vatCategory \"O\" = \"Services outside scope of tax\" (UBL 2.1 / EN 16931).\n // Public entities (SPF Economie) are VAT-exempt. No `taxExemptReason` field\n // exists in InvoiceLine — Storecove derives exemption from the category code.\n // If sandbox returns 422 on this combination, fallback is vatRate: 21 + vatCategory: \"S\".\n vatCategory: \"O\",\n },\n ],\n };\n\n if (overrides.attachment) {\n payload.attachments = [\n {\n id: \"ATT-001\",\n description: \"Test document\",\n filename: \"test.pdf\",\n mimeType: \"application/pdf\",\n content: MINIMAL_TEST_PDF_BASE64,\n },\n ];\n }\n\n return payload;\n}\n","import type { Readable, Writable } from \"node:stream\";\nimport { createInterface } from \"node:readline\";\n\nexport interface ConfirmOptions {\n prompt: string;\n defaultYes: boolean;\n stdin?: Readable;\n stdout?: Writable;\n}\n\nexport async function confirmInteractive(opts: ConfirmOptions): Promise<boolean> {\n const stdin = (opts.stdin ?? process.stdin) as Readable & { isTTY?: boolean };\n const stdout = opts.stdout ?? process.stdout;\n\n // Non-TTY (CI, piped, vitest) → fall back to default.\n // Treat any non-true value (false, undefined) as non-TTY.\n if (stdin.isTTY !== true) {\n return opts.defaultYes;\n }\n\n const suffix = opts.defaultYes ? \"[Y/n]\" : \"[y/N]\";\n return new Promise<boolean>((resolve) => {\n const rl = createInterface({ input: stdin, output: stdout });\n let settled = false;\n\n rl.question(`${opts.prompt} ${suffix} `, (answer) => {\n settled = true;\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === \"\") return resolve(opts.defaultYes);\n if (trimmed === \"y\" || trimmed === \"yes\") return resolve(true);\n if (trimmed === \"n\" || trimmed === \"no\") return resolve(false);\n // Unrecognized input → defaultYes (lenient)\n return resolve(opts.defaultYes);\n });\n\n // Guard: if stdin closes without newline (Ctrl+D, EOF), question callback\n // never fires. Resolve to defaultYes consistent with lenient-fallback policy.\n rl.once(\"close\", () => {\n if (!settled) resolve(opts.defaultYes);\n });\n });\n}\n","export type TerminalStatus = \"delivered\" | \"accepted\" | \"rejected\" | \"failed\";\n\nconst TERMINAL_STATES = new Set<TerminalStatus>([\n \"delivered\",\n \"accepted\",\n \"rejected\",\n \"failed\",\n]);\n\nexport interface WatchOptions {\n intervalMs?: number;\n timeoutMs?: number;\n onTransition?: (status: string) => void;\n}\n\nexport interface WatchResult {\n finalStatus: string;\n timedOut: boolean;\n}\n\ninterface StatusFetcher {\n invoices: { getStatus: (id: string) => Promise<{ status: string }> };\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\nexport async function pollUntilTerminal(\n client: StatusFetcher,\n documentId: string,\n options: WatchOptions = {},\n): Promise<WatchResult> {\n const intervalMs = options.intervalMs ?? 2000;\n const timeoutMs = options.timeoutMs ?? 60_000;\n const start = Date.now();\n\n let lastStatus = \"\";\n\n while (Date.now() - start < timeoutMs) {\n const { status } = await client.invoices.getStatus(documentId);\n\n if (status !== lastStatus) {\n options.onTransition?.(status);\n lastStatus = status;\n }\n\n if (TERMINAL_STATES.has(status as TerminalStatus)) {\n return { finalStatus: status, timedOut: false };\n }\n\n await sleep(intervalMs);\n }\n\n return { finalStatus: lastStatus, timedOut: true };\n}\n","import pc from \"picocolors\";\n\nexport interface SendResultPayload {\n id: string;\n number: string;\n status: string;\n warnings?: { message: string }[];\n dashboardUrl: string;\n}\n\nexport type OutputMode = \"formatted\" | \"json\" | \"quiet\";\n\nexport function formatSendResult(result: SendResultPayload, mode: OutputMode): string {\n if (mode === \"quiet\") return \"\";\n\n if (mode === \"json\") {\n return JSON.stringify(result, null, 2);\n }\n\n // formatted\n const lines: string[] = [];\n lines.push(`${pc.green(\"✓\")} Sent ${pc.bold(result.number)}`);\n lines.push(` id: ${result.id}`);\n lines.push(` Status: ${pc.cyan(result.status)}`);\n lines.push(` Track: ${pc.dim(result.dashboardUrl)}`);\n\n const wCount = result.warnings?.length ?? 0;\n if (wCount > 0) {\n lines.push(` ${pc.yellow(`${wCount} warning${wCount === 1 ? \"\" : \"s\"}`)}`);\n for (const w of result.warnings ?? []) {\n lines.push(` ${pc.yellow(\"⚠\")} ${w.message}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","import { createInterface } from \"node:readline\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { exitWithError } from \"../utils/errors.js\";\nimport {\n getCredentialsPath,\n readCredentials,\n writeCredentials,\n} from \"../lib/credentials-store.js\";\n\ninterface LoginFlags {\n key?: string;\n sandbox?: boolean;\n live?: boolean;\n}\n\nasync function promptMaskedKey(envLabel: string): Promise<string> {\n if (process.stdin.isTTY !== true) {\n exitWithError(\"Error: --key flag required when stdin is not a TTY (CI mode).\");\n }\n\n process.stdout.write(`Paste your ${envLabel} API key (input hidden): `);\n\n return new Promise<string>((resolve) => {\n let buffer = \"\";\n const onData = (chunk: Buffer) => {\n const c = chunk.toString(\"utf-8\");\n if (c === \"\\n\" || c === \"\\r\" || c === \"\\r\\n\") {\n process.stdin.setRawMode(false);\n process.stdin.removeListener(\"data\", onData);\n process.stdin.pause();\n process.stdout.write(\"\\n\");\n resolve(buffer);\n return;\n }\n if (c === \"\\x03\") {\n // Ctrl-C in raw mode: SIGINT is disabled, byte arrives as ETX (0x03)\n process.stdin.setRawMode(false);\n process.stdin.removeListener(\"data\", onData);\n process.stdin.pause();\n process.stdout.write(\"\\n\");\n process.exit(130);\n }\n if (c === \"\\x7f\" || c === \"\\b\") {\n // Backspace: POSIX terminals send DEL (0x7f), some send BS (0x08 / \"\\b\")\n buffer = buffer.slice(0, -1);\n return;\n }\n buffer += c;\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on(\"data\", onData);\n });\n}\n\nasync function promptEnvironment(): Promise<\"sandbox\" | \"live\"> {\n if (process.stdin.isTTY !== true) return \"sandbox\";\n\n return new Promise<\"sandbox\" | \"live\">((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(\"Environment? (s)andbox / (l)ive [sandbox]: \", (answer) => {\n rl.close();\n const a = answer.trim().toLowerCase();\n if (a === \"l\" || a === \"live\") return resolve(\"live\");\n return resolve(\"sandbox\");\n });\n });\n}\n\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .description(\"Save a getpeppr API key to ~/.config/getpeppr/credentials.json\")\n .option(\"--key <key>\", \"API key — for CI/scripted use only; visible in `ps` and shell history. Prefer the interactive prompt or GETPEPPR_API_KEY env var.\")\n .option(\"--sandbox\", \"store as sandbox key (default)\")\n .option(\"--live\", \"store as live (production) key\")\n .action(async (flags: LoginFlags) => {\n if (!flags.live && !flags.sandbox && process.stdin.isTTY !== true) {\n exitWithError(\"Error: --sandbox or --live required when stdin is not a TTY (CI mode).\");\n }\n\n let env: \"sandbox\" | \"live\";\n if (flags.live) env = \"live\";\n else if (flags.sandbox) env = \"sandbox\";\n else env = await promptEnvironment();\n\n let key: string;\n if (flags.key) {\n key = flags.key;\n } else {\n key = (await promptMaskedKey(env)).trim();\n if (!key) exitWithError(\"Error: empty API key.\");\n }\n\n const existing = readCredentials() ?? {};\n const next = { ...existing, [env]: key };\n writeCredentials(next);\n\n const path = getCredentialsPath();\n process.stderr.write(\n `${pc.green(\"✓\")} Saved ${env} key to ${path} (mode 600)\\n`,\n );\n });\n}\n","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { deleteCredentials, getCredentialsPath } from \"../lib/credentials-store.js\";\n\nexport function registerLogoutCommand(program: Command): void {\n program\n .command(\"logout\")\n .description(\"Remove ~/.config/getpeppr/credentials.json\")\n .action(() => {\n const path = getCredentialsPath();\n const removed = deleteCredentials();\n if (removed) {\n process.stderr.write(`${pc.green(\"✓\")} Removed ${path}\\n`);\n } else {\n process.stderr.write(`No credentials to remove (${path})\\n`);\n }\n process.exit(0);\n });\n}\n"],"mappings":"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","names":["warn","resolve","error","program","existsSync","resolve","pc","program","resolve","existsSync","pc","writeFileSync","pc","program","writeFileSync","pc","pc","pc","program","pc","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","resolve","resolve","existsSync","readFileSync","resolve","sleep","pc","program","result","pc","createInterface","pc","resolve","createInterface","program","pc","pc","program","pc","require"]}