ksef-client-ts 0.2.0 → 0.3.0

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
@@ -65,7 +65,8 @@ function resolveOptions(options = {}) {
65
65
  lighthouseUrl: options.lighthouseUrl ?? env.lighthouseUrl,
66
66
  apiVersion: options.apiVersion ?? DEFAULT_API_VERSION,
67
67
  timeout: options.timeout ?? DEFAULT_TIMEOUT,
68
- customHeaders: options.customHeaders ?? {}
68
+ customHeaders: options.customHeaders ?? {},
69
+ environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST")
69
70
  };
70
71
  }
71
72
  var DEFAULT_API_VERSION, DEFAULT_TIMEOUT;
@@ -1573,84 +1574,111 @@ var init_test_data = __esm({
1573
1574
  "use strict";
1574
1575
  init_rest_request();
1575
1576
  init_routes();
1577
+ init_ksef_error();
1576
1578
  TestDataService = class {
1577
1579
  restClient;
1578
- constructor(restClient) {
1580
+ environmentName;
1581
+ constructor(restClient, environmentName) {
1579
1582
  this.restClient = restClient;
1583
+ this.environmentName = environmentName;
1584
+ }
1585
+ ensureTestEnvironment() {
1586
+ if (this.environmentName && this.environmentName !== "TEST") {
1587
+ throw new KSeFError(
1588
+ `Test data APIs are only available on the TEST environment (current: ${this.environmentName})`
1589
+ );
1590
+ }
1580
1591
  }
1581
1592
  // Subject management
1582
1593
  async createSubject(request) {
1594
+ this.ensureTestEnvironment();
1583
1595
  const req = RestRequest.post(Routes.TestData.createSubject).body(request);
1584
1596
  await this.restClient.executeVoid(req);
1585
1597
  }
1586
1598
  async removeSubject(request) {
1599
+ this.ensureTestEnvironment();
1587
1600
  const req = RestRequest.post(Routes.TestData.removeSubject).body(request);
1588
1601
  await this.restClient.executeVoid(req);
1589
1602
  }
1590
1603
  // Person management
1591
1604
  async createPerson(request) {
1605
+ this.ensureTestEnvironment();
1592
1606
  const req = RestRequest.post(Routes.TestData.createPerson).body(request);
1593
1607
  await this.restClient.executeVoid(req);
1594
1608
  }
1595
1609
  async removePerson(request) {
1610
+ this.ensureTestEnvironment();
1596
1611
  const req = RestRequest.post(Routes.TestData.removePerson).body(request);
1597
1612
  await this.restClient.executeVoid(req);
1598
1613
  }
1599
1614
  // Permissions
1600
1615
  async grantPermissions(request) {
1616
+ this.ensureTestEnvironment();
1601
1617
  const req = RestRequest.post(Routes.TestData.grantPerms).body(request);
1602
1618
  await this.restClient.executeVoid(req);
1603
1619
  }
1604
1620
  async revokePermissions(request) {
1621
+ this.ensureTestEnvironment();
1605
1622
  const req = RestRequest.post(Routes.TestData.revokePerms).body(request);
1606
1623
  await this.restClient.executeVoid(req);
1607
1624
  }
1608
1625
  // Attachment permissions
1609
1626
  async enableAttachment(request) {
1627
+ this.ensureTestEnvironment();
1610
1628
  const req = RestRequest.post(Routes.TestData.enableAttach).body(request);
1611
1629
  await this.restClient.executeVoid(req);
1612
1630
  }
1613
1631
  async disableAttachment(request) {
1632
+ this.ensureTestEnvironment();
1614
1633
  const req = RestRequest.post(Routes.TestData.disableAttach).body(request);
1615
1634
  await this.restClient.executeVoid(req);
1616
1635
  }
1617
1636
  // Session limits
1618
1637
  async changeSessionLimits(request) {
1638
+ this.ensureTestEnvironment();
1619
1639
  const req = RestRequest.post(Routes.TestData.changeSessionLimitsInCurrentContext).body(request);
1620
1640
  await this.restClient.executeVoid(req);
1621
1641
  }
1622
1642
  async restoreDefaultSessionLimits() {
1643
+ this.ensureTestEnvironment();
1623
1644
  const req = RestRequest.delete(Routes.TestData.restoreDefaultSessionLimitsInCurrentContext);
1624
1645
  await this.restClient.executeVoid(req);
1625
1646
  }
1626
1647
  // Certificate limits
1627
1648
  async changeCertificatesLimit(request) {
1649
+ this.ensureTestEnvironment();
1628
1650
  const req = RestRequest.post(Routes.TestData.changeCertificatesLimitInCurrentSubject).body(request);
1629
1651
  await this.restClient.executeVoid(req);
1630
1652
  }
1631
1653
  async restoreDefaultCertificatesLimit() {
1654
+ this.ensureTestEnvironment();
1632
1655
  const req = RestRequest.delete(Routes.TestData.restoreDefaultCertificatesLimitInCurrentSubject);
1633
1656
  await this.restClient.executeVoid(req);
1634
1657
  }
1635
1658
  // Rate limits
1636
1659
  async setRateLimits(request) {
1660
+ this.ensureTestEnvironment();
1637
1661
  const req = RestRequest.post(Routes.TestData.rateLimits).body(request);
1638
1662
  await this.restClient.executeVoid(req);
1639
1663
  }
1640
1664
  async restoreDefaultRateLimits() {
1665
+ this.ensureTestEnvironment();
1641
1666
  const req = RestRequest.delete(Routes.TestData.rateLimits);
1642
1667
  await this.restClient.executeVoid(req);
1643
1668
  }
1644
1669
  async setProductionRateLimits() {
1670
+ this.ensureTestEnvironment();
1645
1671
  const req = RestRequest.post(Routes.TestData.productionRateLimits);
1646
1672
  await this.restClient.executeVoid(req);
1647
1673
  }
1648
1674
  // Context blocking
1649
1675
  async blockContext(request) {
1676
+ this.ensureTestEnvironment();
1650
1677
  const req = RestRequest.post(Routes.TestData.blockContext).body(request);
1651
1678
  await this.restClient.executeVoid(req);
1652
1679
  }
1653
1680
  async unblockContext(request) {
1681
+ this.ensureTestEnvironment();
1654
1682
  const req = RestRequest.post(Routes.TestData.unblockContext).body(request);
1655
1683
  await this.restClient.executeVoid(req);
1656
1684
  }
@@ -1727,10 +1755,10 @@ ${lines.join("\n")}
1727
1755
  });
1728
1756
 
1729
1757
  // src/crypto/cryptography-service.ts
1730
- import * as crypto from "crypto";
1758
+ import * as crypto2 from "crypto";
1731
1759
  import * as x509 from "@peculiar/x509";
1732
1760
  function setCryptoProvider() {
1733
- x509.cryptoProvider.set(crypto.webcrypto);
1761
+ x509.cryptoProvider.set(crypto2.webcrypto);
1734
1762
  }
1735
1763
  function buildX500Name(fields) {
1736
1764
  const parts = [];
@@ -1772,12 +1800,12 @@ var init_cryptography_service = __esm({
1772
1800
  // ---------------------------------------------------------------------------
1773
1801
  /** Encrypt with AES-256-CBC (PKCS7 padding is automatic in Node). */
1774
1802
  encryptAES256(content, key, iv) {
1775
- const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
1803
+ const cipher = crypto2.createCipheriv("aes-256-cbc", key, iv);
1776
1804
  return new Uint8Array(Buffer.concat([cipher.update(content), cipher.final()]));
1777
1805
  }
1778
1806
  /** Decrypt with AES-256-CBC. */
1779
1807
  decryptAES256(content, key, iv) {
1780
- const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
1808
+ const decipher = crypto2.createDecipheriv("aes-256-cbc", key, iv);
1781
1809
  return new Uint8Array(Buffer.concat([decipher.update(content), decipher.final()]));
1782
1810
  }
1783
1811
  // ---------------------------------------------------------------------------
@@ -1788,14 +1816,14 @@ var init_cryptography_service = __esm({
1788
1816
  * SymmetricKeyEncryption certificate's RSA public key (RSA-OAEP SHA-256).
1789
1817
  */
1790
1818
  getEncryptionData() {
1791
- const key = crypto.randomBytes(32);
1792
- const iv = crypto.randomBytes(16);
1819
+ const key = crypto2.randomBytes(32);
1820
+ const iv = crypto2.randomBytes(16);
1793
1821
  const certPem = this.fetcher.getSymmetricKeyEncryptionPem();
1794
- const encryptedKey = crypto.publicEncrypt(
1822
+ const encryptedKey = crypto2.publicEncrypt(
1795
1823
  {
1796
1824
  key: certPem,
1797
1825
  oaepHash: "sha256",
1798
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
1826
+ padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
1799
1827
  },
1800
1828
  key
1801
1829
  );
@@ -1829,7 +1857,7 @@ var init_cryptography_service = __esm({
1829
1857
  const timestampMs = new Date(challengeTimestamp).getTime();
1830
1858
  const plaintext = Buffer.from(`${token}|${timestampMs}`, "utf-8");
1831
1859
  const certPem = this.fetcher.getKsefTokenEncryptionPem();
1832
- const cert = new crypto.X509Certificate(certPem);
1860
+ const cert = new crypto2.X509Certificate(certPem);
1833
1861
  const publicKey = cert.publicKey;
1834
1862
  if (publicKey.asymmetricKeyType === "rsa") {
1835
1863
  return this.encryptRsaOaep(certPem, plaintext);
@@ -1844,7 +1872,7 @@ var init_cryptography_service = __esm({
1844
1872
  // ---------------------------------------------------------------------------
1845
1873
  /** Compute SHA-256 hash (base64) and byte length. */
1846
1874
  getFileMetadata(file) {
1847
- const hash = crypto.createHash("sha256").update(file).digest("base64");
1875
+ const hash = crypto2.createHash("sha256").update(file).digest("base64");
1848
1876
  return { hashSHA: hash, fileSize: file.length };
1849
1877
  }
1850
1878
  // ---------------------------------------------------------------------------
@@ -1859,7 +1887,7 @@ var init_cryptography_service = __esm({
1859
1887
  publicExponent: new Uint8Array([1, 0, 1]),
1860
1888
  modulusLength: 2048
1861
1889
  };
1862
- const keys = await crypto.webcrypto.subtle.generateKey(
1890
+ const keys = await crypto2.webcrypto.subtle.generateKey(
1863
1891
  algorithm,
1864
1892
  true,
1865
1893
  ["sign", "verify"]
@@ -1870,7 +1898,7 @@ var init_cryptography_service = __esm({
1870
1898
  signingAlgorithm: algorithm
1871
1899
  });
1872
1900
  const csrDer = new Uint8Array(csr.rawData);
1873
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1901
+ const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1874
1902
  const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
1875
1903
  return { csrDer, privateKeyPem };
1876
1904
  }
@@ -1881,7 +1909,7 @@ var init_cryptography_service = __esm({
1881
1909
  name: "ECDSA",
1882
1910
  namedCurve: "P-256"
1883
1911
  };
1884
- const keys = await crypto.webcrypto.subtle.generateKey(
1912
+ const keys = await crypto2.webcrypto.subtle.generateKey(
1885
1913
  algorithm,
1886
1914
  true,
1887
1915
  ["sign", "verify"]
@@ -1892,7 +1920,7 @@ var init_cryptography_service = __esm({
1892
1920
  signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
1893
1921
  });
1894
1922
  const csrDer = new Uint8Array(csr.rawData);
1895
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1923
+ const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1896
1924
  const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
1897
1925
  return { csrDer, privateKeyPem };
1898
1926
  }
@@ -1901,7 +1929,7 @@ var init_cryptography_service = __esm({
1901
1929
  // ---------------------------------------------------------------------------
1902
1930
  /** Parse a PEM-encoded private key into a Node.js KeyObject. */
1903
1931
  parsePrivateKey(pem) {
1904
- return crypto.createPrivateKey(pem);
1932
+ return crypto2.createPrivateKey(pem);
1905
1933
  }
1906
1934
  // ---------------------------------------------------------------------------
1907
1935
  // Private helpers
@@ -1909,11 +1937,11 @@ var init_cryptography_service = __esm({
1909
1937
  /** RSA-OAEP SHA-256 encryption. */
1910
1938
  encryptRsaOaep(certPem, plaintext) {
1911
1939
  return new Uint8Array(
1912
- crypto.publicEncrypt(
1940
+ crypto2.publicEncrypt(
1913
1941
  {
1914
1942
  key: certPem,
1915
1943
  oaepHash: "sha256",
1916
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
1944
+ padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
1917
1945
  },
1918
1946
  plaintext
1919
1947
  )
@@ -1930,15 +1958,15 @@ var init_cryptography_service = __esm({
1930
1958
  * (Java-compatible — GCM appends the 16-byte tag to the ciphertext).
1931
1959
  */
1932
1960
  encryptEcdhAesGcm(receiverPublicKey, plaintext) {
1933
- const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto.generateKeyPairSync("ec", {
1961
+ const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto2.generateKeyPairSync("ec", {
1934
1962
  namedCurve: "prime256v1"
1935
1963
  });
1936
- const sharedSecret = crypto.diffieHellman({
1964
+ const sharedSecret = crypto2.diffieHellman({
1937
1965
  privateKey: ephPrivKey,
1938
1966
  publicKey: receiverPublicKey
1939
1967
  });
1940
- const nonce = crypto.randomBytes(12);
1941
- const cipher = crypto.createCipheriv("aes-256-gcm", sharedSecret, nonce);
1968
+ const nonce = crypto2.randomBytes(12);
1969
+ const cipher = crypto2.createCipheriv("aes-256-gcm", sharedSecret, nonce);
1942
1970
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1943
1971
  const tag = cipher.getAuthTag();
1944
1972
  const ephemeralSpki = ephPubKey.export({ type: "spki", format: "der" });
@@ -6489,7 +6517,7 @@ var signature_service_exports = {};
6489
6517
  __export(signature_service_exports, {
6490
6518
  SignatureService: () => SignatureService
6491
6519
  });
6492
- import * as crypto2 from "crypto";
6520
+ import * as crypto3 from "crypto";
6493
6521
  import { ExclusiveCanonicalization } from "xml-crypto";
6494
6522
  function extractDerFromPem(pem) {
6495
6523
  const base64 = pem.replace(/-----BEGIN [A-Z\s]+-----/g, "").replace(/-----END [A-Z\s]+-----/g, "").replace(/\s+/g, "");
@@ -6508,7 +6536,7 @@ function canonicalize(elem) {
6508
6536
  function computeRootDigest(doc) {
6509
6537
  const root = doc.documentElement;
6510
6538
  const canonical = canonicalize(root);
6511
- return crypto2.createHash("sha256").update(canonical, "utf-8").digest("base64");
6539
+ return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
6512
6540
  }
6513
6541
  function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
6514
6542
  const parser = new import_xmldom.DOMParser();
@@ -6518,7 +6546,7 @@ function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
6518
6546
  throw new Error("SignedProperties element not found in QualifyingProperties");
6519
6547
  }
6520
6548
  const canonical = canonicalize(signedProps);
6521
- return crypto2.createHash("sha256").update(canonical, "utf-8").digest("base64");
6549
+ return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
6522
6550
  }
6523
6551
  function buildSignedInfo(signatureAlgorithm, rootDigest, signedPropertiesDigest) {
6524
6552
  return [
@@ -6549,12 +6577,12 @@ function computeSignatureValue(canonicalSignedInfo, privateKeyPem, isEc) {
6549
6577
  const data = Buffer.from(canonicalSignedInfo, "utf-8");
6550
6578
  let signature;
6551
6579
  if (isEc) {
6552
- signature = crypto2.sign("sha256", data, {
6580
+ signature = crypto3.sign("sha256", data, {
6553
6581
  key: privateKeyPem,
6554
6582
  dsaEncoding: "ieee-p1363"
6555
6583
  });
6556
6584
  } else {
6557
- signature = crypto2.sign("sha256", data, privateKeyPem);
6585
+ signature = crypto3.sign("sha256", data, privateKeyPem);
6558
6586
  }
6559
6587
  return signature.toString("base64");
6560
6588
  }
@@ -6654,11 +6682,11 @@ var init_signature_service = __esm({
6654
6682
  }
6655
6683
  const certDer = extractDerFromPem(certPem);
6656
6684
  const certBase64 = certDer.toString("base64");
6657
- const certDigest = crypto2.createHash("sha256").update(certDer).digest("base64");
6658
- const x5093 = new crypto2.X509Certificate(certPem);
6685
+ const certDigest = crypto3.createHash("sha256").update(certDer).digest("base64");
6686
+ const x5093 = new crypto3.X509Certificate(certPem);
6659
6687
  const issuerName = normalizeIssuerDn(x5093.issuer);
6660
6688
  const serialNumber = hexSerialToDecimal(x5093.serialNumber);
6661
- const privateKey = crypto2.createPrivateKey(privateKeyPem);
6689
+ const privateKey = crypto3.createPrivateKey(privateKeyPem);
6662
6690
  const isEc = privateKey.asymmetricKeyType === "ec";
6663
6691
  const signatureAlgorithm = isEc ? ECDSA_SHA256_SIGNATURE : RSA_SHA256_SIGNATURE;
6664
6692
  const signingTime = new Date(Date.now() + CLOCK_SKEW_BUFFER_MS).toISOString();
@@ -6762,7 +6790,7 @@ var init_pkcs12_loader = __esm({
6762
6790
  });
6763
6791
 
6764
6792
  // src/qr/verification-link-service.ts
6765
- import crypto4 from "crypto";
6793
+ import crypto5 from "crypto";
6766
6794
  var VerificationLinkService;
6767
6795
  var init_verification_link_service = __esm({
6768
6796
  "src/qr/verification-link-service.ts"() {
@@ -6792,16 +6820,16 @@ var init_verification_link_service = __esm({
6792
6820
  const hashBase64Url = this.base64ToBase64Url(invoiceHashBase64);
6793
6821
  const pathWithoutSignature = `${this.baseQrUrl}/certificate/${contextType}/${contextId}/${sellerNip}/${certSerial}/${hashBase64Url}`;
6794
6822
  const dataToSign = pathWithoutSignature.replace(/^https?:\/\//, "");
6795
- const key = crypto4.createPrivateKey(privateKeyPem);
6823
+ const key = crypto5.createPrivateKey(privateKeyPem);
6796
6824
  let signature;
6797
6825
  if (key.asymmetricKeyType === "rsa") {
6798
- signature = crypto4.sign("sha256", Buffer.from(dataToSign), {
6826
+ signature = crypto5.sign("sha256", Buffer.from(dataToSign), {
6799
6827
  key,
6800
- padding: crypto4.constants.RSA_PKCS1_PSS_PADDING,
6828
+ padding: crypto5.constants.RSA_PKCS1_PSS_PADDING,
6801
6829
  saltLength: 32
6802
6830
  });
6803
6831
  } else if (key.asymmetricKeyType === "ec") {
6804
- signature = crypto4.sign("sha256", Buffer.from(dataToSign), {
6832
+ signature = crypto5.sign("sha256", Buffer.from(dataToSign), {
6805
6833
  key,
6806
6834
  dsaEncoding: "ieee-p1363"
6807
6835
  });
@@ -6933,7 +6961,7 @@ var init_client = __esm({
6933
6961
  this.lighthouse = new LighthouseService(this.options);
6934
6962
  this.limits = new LimitsService(restClient);
6935
6963
  this.peppol = new PeppolService(restClient);
6936
- this.testData = new TestDataService(restClient);
6964
+ this.testData = new TestDataService(restClient, this.options.environmentName);
6937
6965
  this.qr = new VerificationLinkService(this.options.baseQrUrl);
6938
6966
  }
6939
6967
  async loginWithToken(token, nip) {
@@ -7480,18 +7508,86 @@ var AuthorizationPermissionGrantBuilder = class {
7480
7508
  }
7481
7509
  };
7482
7510
 
7511
+ // src/builders/batch-file.ts
7512
+ init_ksef_validation_error();
7513
+ import * as crypto from "crypto";
7514
+ var BATCH_MAX_PART_SIZE = 1e8;
7515
+ var BATCH_MAX_TOTAL_SIZE = 5e9;
7516
+ var BATCH_MAX_PARTS = 50;
7517
+ var BatchFileBuilder = class {
7518
+ /**
7519
+ * Build batch file metadata and encrypted parts from a raw ZIP.
7520
+ *
7521
+ * @param zipBytes - Unencrypted ZIP data
7522
+ * @param encryptFn - AES-256-CBC encryption function (called per part)
7523
+ * @param options - Optional configuration
7524
+ */
7525
+ static build(zipBytes, encryptFn, options) {
7526
+ const maxPartSize = options?.maxPartSize ?? BATCH_MAX_PART_SIZE;
7527
+ if (maxPartSize <= 0) {
7528
+ throw new KSeFValidationError("maxPartSize must be a positive number");
7529
+ }
7530
+ if (zipBytes.length === 0) {
7531
+ throw new KSeFValidationError("ZIP data must not be empty");
7532
+ }
7533
+ if (zipBytes.length > BATCH_MAX_TOTAL_SIZE) {
7534
+ throw new KSeFValidationError(
7535
+ `ZIP size ${zipBytes.length} exceeds maximum of ${BATCH_MAX_TOTAL_SIZE} bytes (5 GB)`
7536
+ );
7537
+ }
7538
+ const rawParts = splitBuffer(zipBytes, maxPartSize);
7539
+ if (rawParts.length > BATCH_MAX_PARTS) {
7540
+ throw new KSeFValidationError(
7541
+ `Data requires ${rawParts.length} parts, exceeding maximum of ${BATCH_MAX_PARTS}`
7542
+ );
7543
+ }
7544
+ const zipHash = sha256Base64(zipBytes);
7545
+ const encryptedParts = [];
7546
+ const fileParts = rawParts.map((raw, i) => {
7547
+ const encrypted = encryptFn(raw);
7548
+ encryptedParts.push(encrypted);
7549
+ return {
7550
+ ordinalNumber: i + 1,
7551
+ fileSize: encrypted.length,
7552
+ fileHash: sha256Base64(encrypted)
7553
+ };
7554
+ });
7555
+ return {
7556
+ batchFile: {
7557
+ fileSize: zipBytes.length,
7558
+ fileHash: zipHash,
7559
+ fileParts
7560
+ },
7561
+ encryptedParts
7562
+ };
7563
+ }
7564
+ };
7565
+ function splitBuffer(data, maxPartSize) {
7566
+ if (data.length <= maxPartSize) {
7567
+ return [data];
7568
+ }
7569
+ const parts = [];
7570
+ for (let offset = 0; offset < data.length; offset += maxPartSize) {
7571
+ parts.push(data.subarray(offset, Math.min(offset + maxPartSize, data.length)));
7572
+ }
7573
+ return parts;
7574
+ }
7575
+ function sha256Base64(data) {
7576
+ return crypto.createHash("sha256").update(data).digest("base64");
7577
+ }
7578
+
7483
7579
  // src/crypto/index.ts
7484
7580
  init_certificate_fetcher();
7485
7581
  init_cryptography_service();
7486
7582
  init_signature_service();
7487
7583
 
7488
7584
  // src/crypto/certificate-service.ts
7489
- import * as crypto3 from "crypto";
7585
+ import * as crypto4 from "crypto";
7490
7586
  import * as x5092 from "@peculiar/x509";
7491
7587
  var CertificateService = class {
7492
7588
  static getSha256Fingerprint(certPem) {
7493
7589
  const der = extractDerFromPem2(certPem);
7494
- return crypto3.createHash("sha256").update(der).digest("hex").toUpperCase();
7590
+ return crypto4.createHash("sha256").update(der).digest("hex").toUpperCase();
7495
7591
  }
7496
7592
  static async generatePersonalCertificate(givenName, surname, serialNumber, commonName, method = "RSA") {
7497
7593
  const nameParts = [];
@@ -7514,7 +7610,7 @@ var CertificateService = class {
7514
7610
  }
7515
7611
  };
7516
7612
  async function generateSelfSigned(subject, method) {
7517
- x5092.cryptoProvider.set(crypto3.webcrypto);
7613
+ x5092.cryptoProvider.set(crypto4.webcrypto);
7518
7614
  let algorithm;
7519
7615
  let signingAlgorithm;
7520
7616
  if (method === "ECDSA") {
@@ -7529,7 +7625,7 @@ async function generateSelfSigned(subject, method) {
7529
7625
  };
7530
7626
  signingAlgorithm = algorithm;
7531
7627
  }
7532
- const keys = await crypto3.webcrypto.subtle.generateKey(
7628
+ const keys = await crypto4.webcrypto.subtle.generateKey(
7533
7629
  algorithm,
7534
7630
  true,
7535
7631
  ["sign", "verify"]
@@ -7546,9 +7642,9 @@ async function generateSelfSigned(subject, method) {
7546
7642
  serialNumber: Date.now().toString(16)
7547
7643
  });
7548
7644
  const certPem = cert.toString("pem");
7549
- const pkcs8 = await crypto3.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7645
+ const pkcs8 = await crypto4.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7550
7646
  const privateKeyPem = pemEncode2(new Uint8Array(pkcs8), "PRIVATE KEY");
7551
- const fingerprint = crypto3.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
7647
+ const fingerprint = crypto4.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
7552
7648
  return { certificatePem: certPem, privateKeyPem, fingerprint };
7553
7649
  }
7554
7650
  function extractDerFromPem2(pem) {
@@ -7682,7 +7778,7 @@ async function openOnlineSession(client, options) {
7682
7778
  async waitForUpo(pollOpts) {
7683
7779
  const result = await pollUntil(
7684
7780
  () => client.sessionStatus.getSessionStatus(sessionRef),
7685
- (s) => s.status.code !== 100,
7781
+ (s) => s.status.code === 200 || s.status.code >= 400,
7686
7782
  { ...pollOpts, description: `UPO for session ${sessionRef}` }
7687
7783
  );
7688
7784
  if (result.status.code !== 200) {
@@ -7708,31 +7804,36 @@ async function openSendAndClose(client, invoices, options) {
7708
7804
 
7709
7805
  // src/workflows/batch-session-workflow.ts
7710
7806
  var DEFAULT_FORM_CODE2 = { systemCode: "FA", schemaVersion: "3", value: "FA (3)" };
7711
- async function uploadBatch(client, zipParts, totalFileSize, totalFileHash, options) {
7807
+ async function uploadBatch(client, zipData, options) {
7712
7808
  await client.crypto.init();
7713
7809
  const encData = client.crypto.getEncryptionData();
7714
7810
  const formCode = options?.formCode ?? DEFAULT_FORM_CODE2;
7715
- const fileParts = zipParts.map((part, i) => {
7716
- const meta = client.crypto.getFileMetadata(new Uint8Array(part.data));
7717
- return { ordinalNumber: i + 1, fileSize: meta.fileSize, fileHash: meta.hashSHA };
7811
+ const encryptFn = (part) => client.crypto.encryptAES256(part, encData.cipherKey, encData.cipherIv);
7812
+ const { batchFile, encryptedParts } = BatchFileBuilder.build(zipData, encryptFn, {
7813
+ maxPartSize: options?.maxPartSize
7718
7814
  });
7719
7815
  const openResp = await client.batchSession.openSession(
7720
7816
  {
7721
7817
  formCode,
7722
7818
  encryption: encData.encryptionInfo,
7723
- batchFile: { fileSize: totalFileSize, fileHash: totalFileHash, fileParts }
7819
+ batchFile,
7820
+ offlineMode: options?.offlineMode
7724
7821
  },
7725
7822
  options?.upoVersion
7726
7823
  );
7727
- const sendingParts = zipParts.map((part, i) => {
7728
- const meta = client.crypto.getFileMetadata(new Uint8Array(part.data));
7729
- return { data: part.data, metadata: meta, ordinalNumber: i + 1 };
7730
- });
7824
+ const sendingParts = encryptedParts.map((part, i) => ({
7825
+ data: part.buffer.slice(part.byteOffset, part.byteOffset + part.byteLength),
7826
+ metadata: {
7827
+ hashSHA: batchFile.fileParts[i].fileHash,
7828
+ fileSize: batchFile.fileParts[i].fileSize
7829
+ },
7830
+ ordinalNumber: i + 1
7831
+ }));
7731
7832
  await client.batchSession.sendParts(openResp, sendingParts);
7732
7833
  await client.batchSession.closeSession(openResp.referenceNumber);
7733
7834
  const result = await pollUntil(
7734
7835
  () => client.sessionStatus.getSessionStatus(openResp.referenceNumber),
7735
- (s) => s.status.code !== 100,
7836
+ (s) => s.status.code === 200 || s.status.code >= 400,
7736
7837
  { ...options?.pollOptions, description: `UPO for batch ${openResp.referenceNumber}` }
7737
7838
  );
7738
7839
  if (result.status.code !== 200) {
@@ -7750,7 +7851,7 @@ async function uploadBatch(client, zipParts, totalFileSize, totalFileHash, optio
7750
7851
  }
7751
7852
 
7752
7853
  // src/workflows/invoice-export-workflow.ts
7753
- async function exportInvoices(client, filters, options) {
7854
+ async function doExport(client, filters, options) {
7754
7855
  await client.crypto.init();
7755
7856
  const encData = client.crypto.getEncryptionData();
7756
7857
  const opResp = await client.invoices.exportInvoices({
@@ -7760,7 +7861,7 @@ async function exportInvoices(client, filters, options) {
7760
7861
  });
7761
7862
  const result = await pollUntil(
7762
7863
  () => client.invoices.getInvoiceExportStatus(opResp.referenceNumber),
7763
- (s) => s.status.code !== 100,
7864
+ (s) => s.status.code === 200 || s.status.code >= 400,
7764
7865
  { ...options?.pollOptions, description: `export ${opResp.referenceNumber}` }
7765
7866
  );
7766
7867
  if (result.status.code !== 200) {
@@ -7770,23 +7871,29 @@ async function exportInvoices(client, filters, options) {
7770
7871
  throw new Error("Export completed but no package available");
7771
7872
  }
7772
7873
  return {
7773
- parts: result.package.parts.map((p) => ({
7774
- ordinalNumber: p.ordinalNumber,
7775
- url: p.url,
7776
- method: p.method,
7777
- partSize: p.partSize,
7778
- encryptedPartSize: p.encryptedPartSize,
7779
- encryptedPartHash: p.encryptedPartHash,
7780
- expirationDate: p.expirationDate
7781
- })),
7782
- invoiceCount: result.package.invoiceCount,
7783
- isTruncated: result.package.isTruncated,
7784
- permanentStorageHwmDate: result.package.permanentStorageHwmDate
7874
+ encData,
7875
+ result: {
7876
+ parts: result.package.parts.map((p) => ({
7877
+ ordinalNumber: p.ordinalNumber,
7878
+ url: p.url,
7879
+ method: p.method,
7880
+ partSize: p.partSize,
7881
+ encryptedPartSize: p.encryptedPartSize,
7882
+ encryptedPartHash: p.encryptedPartHash,
7883
+ expirationDate: p.expirationDate
7884
+ })),
7885
+ invoiceCount: result.package.invoiceCount,
7886
+ isTruncated: result.package.isTruncated,
7887
+ permanentStorageHwmDate: result.package.permanentStorageHwmDate
7888
+ }
7785
7889
  };
7786
7890
  }
7891
+ async function exportInvoices(client, filters, options) {
7892
+ const { result } = await doExport(client, filters, options);
7893
+ return result;
7894
+ }
7787
7895
  async function exportAndDownload(client, filters, options) {
7788
- const encData = client.crypto.getEncryptionData();
7789
- const exportResult = await exportInvoices(client, filters, options);
7896
+ const { result: exportResult, encData } = await doExport(client, filters, options);
7790
7897
  const download = options?.transport ?? fetch;
7791
7898
  const decryptedParts = [];
7792
7899
  for (const part of exportResult.parts) {
@@ -7879,7 +7986,11 @@ export {
7879
7986
  AuthService,
7880
7987
  AuthTokenRequestBuilder,
7881
7988
  AuthorizationPermissionGrantBuilder,
7989
+ BATCH_MAX_PARTS,
7990
+ BATCH_MAX_PART_SIZE,
7991
+ BATCH_MAX_TOTAL_SIZE,
7882
7992
  Base64String,
7993
+ BatchFileBuilder,
7883
7994
  BatchSessionService,
7884
7995
  CERTIFICATE_NAME_MAX_LENGTH,
7885
7996
  CERTIFICATE_NAME_MIN_LENGTH,