@getpeppr/cli 0.4.5 → 0.4.6

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 CHANGED
@@ -1059,7 +1059,7 @@ function validateInvoice(input) {
1059
1059
  }
1060
1060
 
1061
1061
  // ../sdk/dist/version.js
1062
- var SDK_VERSION = "1.5.2";
1062
+ var SDK_VERSION = "1.9.0";
1063
1063
 
1064
1064
  // ../sdk/dist/core/client.js
1065
1065
  function findHeaderCaseInsensitive(headers, name) {
@@ -1286,12 +1286,7 @@ var GetpepprAdapter = class {
1286
1286
  const invoices = result.invoices ?? result.data ?? [];
1287
1287
  const meta = result.meta;
1288
1288
  return {
1289
- data: invoices.map((inv) => ({
1290
- id: String(inv.id ?? ""),
1291
- number: String(inv.number ?? ""),
1292
- status: mapStatus(String(inv.state ?? inv.status ?? "submitted")),
1293
- createdAt: inv.created_at ? String(inv.created_at) : void 0
1294
- })),
1289
+ data: invoices.map(parseInvoiceSummary),
1295
1290
  meta: {
1296
1291
  totalCount: Number(meta?.total_count ?? invoices.length),
1297
1292
  offset: Number(meta?.offset ?? options?.offset ?? 0),
@@ -1491,6 +1486,58 @@ var GetpepprAdapter = class {
1491
1486
  async deleteContact(id) {
1492
1487
  await this.request("DELETE", `/contacts/${id}`);
1493
1488
  }
1489
+ async createLegalEntity(input, options) {
1490
+ const headers = {};
1491
+ if (options?.idempotencyKey)
1492
+ headers["Idempotency-Key"] = options.idempotencyKey;
1493
+ const result = await this.request("POST", "/legal-entities", input, headers);
1494
+ return parseLegalEntity(result);
1495
+ }
1496
+ async getLegalEntity(id) {
1497
+ const result = await this.request("GET", `/legal-entities/${id}`);
1498
+ return parseLegalEntity(result);
1499
+ }
1500
+ async listLegalEntities(options) {
1501
+ const params = new URLSearchParams();
1502
+ if (options?.limit != null)
1503
+ params.set("limit", String(options.limit));
1504
+ if (options?.offset != null)
1505
+ params.set("offset", String(options.offset));
1506
+ const query = params.toString() ? `?${params.toString()}` : "";
1507
+ const result = await this.request("GET", `/legal-entities${query}`);
1508
+ const rows = result.data ?? [];
1509
+ const pagination = result.pagination;
1510
+ return {
1511
+ data: rows.map(parseLegalEntity),
1512
+ meta: {
1513
+ totalCount: Number(pagination?.total_count ?? rows.length),
1514
+ offset: Number(pagination?.offset ?? options?.offset ?? 0),
1515
+ limit: Number(pagination?.limit ?? options?.limit ?? 50),
1516
+ hasMore: Boolean(pagination?.has_more ?? false),
1517
+ truncated: false
1518
+ }
1519
+ };
1520
+ }
1521
+ async archiveLegalEntity(id) {
1522
+ const result = await this.request("DELETE", `/legal-entities/${id}`);
1523
+ return {
1524
+ id: String(result.id ?? id),
1525
+ externalId: result.externalId != null ? String(result.externalId) : null,
1526
+ status: "archived"
1527
+ };
1528
+ }
1529
+ async requestLegalEntityAttestation(id, input, options) {
1530
+ const headers = {};
1531
+ if (options?.idempotencyKey)
1532
+ headers["Idempotency-Key"] = options.idempotencyKey;
1533
+ const result = await this.request("POST", `/legal-entities/${id}/attestation`, input, headers);
1534
+ return {
1535
+ id: String(result.id ?? id),
1536
+ externalId: result.externalId != null ? String(result.externalId) : null,
1537
+ status: String(result.status ?? ""),
1538
+ expiresAt: String(result.expiresAt ?? "")
1539
+ };
1540
+ }
1494
1541
  async listBankAccounts(options) {
1495
1542
  const params = new URLSearchParams();
1496
1543
  if (options?.limit != null)
@@ -1667,6 +1714,44 @@ function parseContact(raw) {
1667
1714
  contact.directoryLastChecked = String(raw.directoryLastChecked);
1668
1715
  return contact;
1669
1716
  }
1717
+ function parseLegalEntity(raw) {
1718
+ const idObj = raw.identifier;
1719
+ const le = {
1720
+ id: String(raw.id ?? ""),
1721
+ externalId: raw.externalId != null ? String(raw.externalId) : null,
1722
+ companyName: raw.companyName != null ? String(raw.companyName) : null,
1723
+ country: raw.country != null ? String(raw.country) : null,
1724
+ identifier: idObj && idObj.scheme != null && idObj.value != null ? { scheme: String(idObj.scheme), value: String(idObj.value) } : null,
1725
+ status: String(raw.status ?? "pending"),
1726
+ environment: String(raw.environment ?? ""),
1727
+ createdAt: String(raw.createdAt ?? "")
1728
+ };
1729
+ if (raw.verificationDetail != null) {
1730
+ le.verificationDetail = raw.verificationDetail;
1731
+ }
1732
+ return le;
1733
+ }
1734
+ function parseInvoiceSummary(raw) {
1735
+ const summary = {
1736
+ id: String(raw.id ?? ""),
1737
+ number: String(raw.invoiceNumber ?? raw.number ?? ""),
1738
+ status: mapStatus(String(raw.state ?? raw.status ?? "submitted"))
1739
+ };
1740
+ if (raw.createdAt != null)
1741
+ summary.createdAt = String(raw.createdAt);
1742
+ if (typeof raw.isCreditNote === "boolean")
1743
+ summary.isCreditNote = raw.isCreditNote;
1744
+ if (raw.recipientName != null)
1745
+ summary.recipientName = String(raw.recipientName);
1746
+ if (raw.totalAmount != null && Number.isFinite(Number(raw.totalAmount))) {
1747
+ summary.totalAmount = Number(raw.totalAmount);
1748
+ }
1749
+ if (raw.currency != null)
1750
+ summary.currency = String(raw.currency);
1751
+ if (raw.environment != null)
1752
+ summary.environment = String(raw.environment);
1753
+ return summary;
1754
+ }
1670
1755
  function parseBankAccount(raw) {
1671
1756
  const account = {
1672
1757
  id: String(raw.id ?? ""),
@@ -1745,6 +1830,19 @@ var PeppolApiError = class extends PeppolError {
1745
1830
  this.name = "PeppolApiError";
1746
1831
  this.retryAfterMs = retryAfterMs;
1747
1832
  }
1833
+ /**
1834
+ * The gateway's machine-readable error code, parsed from the JSON response body
1835
+ * (e.g. "le_cap_exceeded", "identifier_immutable", "legal_entity_locked", "forbidden").
1836
+ * Returns undefined when the body is not JSON or carries no string `code`.
1837
+ */
1838
+ get code() {
1839
+ try {
1840
+ const parsed = JSON.parse(this.responseBody);
1841
+ return typeof parsed?.code === "string" ? parsed.code : void 0;
1842
+ } catch {
1843
+ return void 0;
1844
+ }
1845
+ }
1748
1846
  };
1749
1847
  var Peppol = class {
1750
1848
  adapter;
@@ -1755,6 +1853,7 @@ var Peppol = class {
1755
1853
  contacts;
1756
1854
  bankAccounts;
1757
1855
  transports;
1856
+ legalEntities;
1758
1857
  constructor(config) {
1759
1858
  if (!config.apiKey) {
1760
1859
  throw new PeppolError("API key is required. Sign up at https://console.getpeppr.dev to get your sandbox key.");
@@ -1767,6 +1866,7 @@ var Peppol = class {
1767
1866
  this.contacts = new ContactOperations(this.adapter);
1768
1867
  this.bankAccounts = new BankAccountOperations(this.adapter);
1769
1868
  this.transports = new TransportOperations(this.adapter);
1869
+ this.legalEntities = new LegalEntityOperations(this.adapter);
1770
1870
  }
1771
1871
  /**
1772
1872
  * Validate an invoice without sending it.
@@ -2288,6 +2388,74 @@ var ContactOperations = class {
2288
2388
  return paginate((offset, limit) => this.adapter.listContacts({ ...options, offset, limit }), options);
2289
2389
  }
2290
2390
  };
2391
+ var LegalEntityOperations = class {
2392
+ adapter;
2393
+ constructor(adapter) {
2394
+ this.adapter = adapter;
2395
+ }
2396
+ /**
2397
+ * Create a sub-tenant Legal Entity for one of your customers.
2398
+ *
2399
+ * Idempotent on `externalId`: repeated calls with the same `externalId` return
2400
+ * the existing entity (HTTP 200) instead of creating a duplicate. Transient 5xx
2401
+ * failures are NOT auto-retried unless you pass `options.idempotencyKey`.
2402
+ *
2403
+ * @example
2404
+ * ```ts
2405
+ * const le = await peppol.legalEntities.create({
2406
+ * externalId: "tenant-42",
2407
+ * companyName: "Acme Health AB",
2408
+ * country: "SE",
2409
+ * address: { line1: "Storgatan 1", city: "Stockholm", zip: "11122" },
2410
+ * identifier: { scheme: "0007", value: "5560000001" },
2411
+ * }, { idempotencyKey: "tenant-42-create" });
2412
+ * ```
2413
+ */
2414
+ async create(input, options) {
2415
+ return this.adapter.createLegalEntity(input, options);
2416
+ }
2417
+ /**
2418
+ * Fetch a single sub-tenant Legal Entity by id. For production entities the
2419
+ * `status` reflects the attestation lifecycle (awaiting_authz → attested → active).
2420
+ */
2421
+ async get(id) {
2422
+ return this.adapter.getLegalEntity(id);
2423
+ }
2424
+ /** List your sub-tenant Legal Entities, newest first. */
2425
+ async list(options) {
2426
+ return this.adapter.listLegalEntities(options);
2427
+ }
2428
+ /**
2429
+ * Async iterator over all sub-tenant Legal Entities, handling pagination.
2430
+ *
2431
+ * @example
2432
+ * ```ts
2433
+ * for await (const le of peppol.legalEntities.listAll()) console.log(le.id, le.status);
2434
+ * ```
2435
+ */
2436
+ listAll(options) {
2437
+ return paginate((offset, limit) => this.adapter.listLegalEntities({ ...options, offset, limit }), options);
2438
+ }
2439
+ /** Archive (soft-delete) a sub-tenant Legal Entity. The id stays resolvable for audit. */
2440
+ async archive(id) {
2441
+ return this.adapter.archiveLegalEntity(id);
2442
+ }
2443
+ /**
2444
+ * Request a sub-tenant attestation (production only). Emails the co-branded
2445
+ * confirmation link to the sub-tenant contact and returns the pending status.
2446
+ *
2447
+ * Transient failures are NOT auto-retried unless you pass `options.idempotencyKey`;
2448
+ * re-issuing mints a fresh token, so a retried call is safe.
2449
+ *
2450
+ * @example
2451
+ * ```ts
2452
+ * await peppol.legalEntities.requestAttestation(le.id, { contactEmail: "owner@acme.example" });
2453
+ * ```
2454
+ */
2455
+ async requestAttestation(id, input, options) {
2456
+ return this.adapter.requestLegalEntityAttestation(id, input, options);
2457
+ }
2458
+ };
2291
2459
  var BankAccountOperations = class {
2292
2460
  adapter;
2293
2461
  constructor(adapter) {
@@ -2917,6 +3085,11 @@ function registerInitCommand(program2) {
2917
3085
  1. Edit the file with your invoice data
2918
3086
  2. Validate: getpeppr validate ${filename}
2919
3087
  3. Convert to XML: getpeppr convert ${filename}
3088
+ 4. Send: getpeppr send ${filename}
3089
+
3090
+ ${pc2.dim("Sandbox note:")} this template includes VAT. To send it on a sandbox
3091
+ account, first register your VAT in Settings \u2192 Peppol Identity, or set each
3092
+ line's "vatCategory" to "O" (outside the scope of VAT) for a no-VAT test send.
2920
3093
  `);
2921
3094
  process.exit(0);
2922
3095
  }