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.cjs CHANGED
@@ -67,7 +67,8 @@ function resolveOptions(options = {}) {
67
67
  lighthouseUrl: options.lighthouseUrl ?? env.lighthouseUrl,
68
68
  apiVersion: options.apiVersion ?? DEFAULT_API_VERSION,
69
69
  timeout: options.timeout ?? DEFAULT_TIMEOUT,
70
- customHeaders: options.customHeaders ?? {}
70
+ customHeaders: options.customHeaders ?? {},
71
+ environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST")
71
72
  };
72
73
  }
73
74
  var DEFAULT_API_VERSION, DEFAULT_TIMEOUT;
@@ -1575,84 +1576,111 @@ var init_test_data = __esm({
1575
1576
  "use strict";
1576
1577
  init_rest_request();
1577
1578
  init_routes();
1579
+ init_ksef_error();
1578
1580
  TestDataService = class {
1579
1581
  restClient;
1580
- constructor(restClient) {
1582
+ environmentName;
1583
+ constructor(restClient, environmentName) {
1581
1584
  this.restClient = restClient;
1585
+ this.environmentName = environmentName;
1586
+ }
1587
+ ensureTestEnvironment() {
1588
+ if (this.environmentName && this.environmentName !== "TEST") {
1589
+ throw new KSeFError(
1590
+ `Test data APIs are only available on the TEST environment (current: ${this.environmentName})`
1591
+ );
1592
+ }
1582
1593
  }
1583
1594
  // Subject management
1584
1595
  async createSubject(request) {
1596
+ this.ensureTestEnvironment();
1585
1597
  const req = RestRequest.post(Routes.TestData.createSubject).body(request);
1586
1598
  await this.restClient.executeVoid(req);
1587
1599
  }
1588
1600
  async removeSubject(request) {
1601
+ this.ensureTestEnvironment();
1589
1602
  const req = RestRequest.post(Routes.TestData.removeSubject).body(request);
1590
1603
  await this.restClient.executeVoid(req);
1591
1604
  }
1592
1605
  // Person management
1593
1606
  async createPerson(request) {
1607
+ this.ensureTestEnvironment();
1594
1608
  const req = RestRequest.post(Routes.TestData.createPerson).body(request);
1595
1609
  await this.restClient.executeVoid(req);
1596
1610
  }
1597
1611
  async removePerson(request) {
1612
+ this.ensureTestEnvironment();
1598
1613
  const req = RestRequest.post(Routes.TestData.removePerson).body(request);
1599
1614
  await this.restClient.executeVoid(req);
1600
1615
  }
1601
1616
  // Permissions
1602
1617
  async grantPermissions(request) {
1618
+ this.ensureTestEnvironment();
1603
1619
  const req = RestRequest.post(Routes.TestData.grantPerms).body(request);
1604
1620
  await this.restClient.executeVoid(req);
1605
1621
  }
1606
1622
  async revokePermissions(request) {
1623
+ this.ensureTestEnvironment();
1607
1624
  const req = RestRequest.post(Routes.TestData.revokePerms).body(request);
1608
1625
  await this.restClient.executeVoid(req);
1609
1626
  }
1610
1627
  // Attachment permissions
1611
1628
  async enableAttachment(request) {
1629
+ this.ensureTestEnvironment();
1612
1630
  const req = RestRequest.post(Routes.TestData.enableAttach).body(request);
1613
1631
  await this.restClient.executeVoid(req);
1614
1632
  }
1615
1633
  async disableAttachment(request) {
1634
+ this.ensureTestEnvironment();
1616
1635
  const req = RestRequest.post(Routes.TestData.disableAttach).body(request);
1617
1636
  await this.restClient.executeVoid(req);
1618
1637
  }
1619
1638
  // Session limits
1620
1639
  async changeSessionLimits(request) {
1640
+ this.ensureTestEnvironment();
1621
1641
  const req = RestRequest.post(Routes.TestData.changeSessionLimitsInCurrentContext).body(request);
1622
1642
  await this.restClient.executeVoid(req);
1623
1643
  }
1624
1644
  async restoreDefaultSessionLimits() {
1645
+ this.ensureTestEnvironment();
1625
1646
  const req = RestRequest.delete(Routes.TestData.restoreDefaultSessionLimitsInCurrentContext);
1626
1647
  await this.restClient.executeVoid(req);
1627
1648
  }
1628
1649
  // Certificate limits
1629
1650
  async changeCertificatesLimit(request) {
1651
+ this.ensureTestEnvironment();
1630
1652
  const req = RestRequest.post(Routes.TestData.changeCertificatesLimitInCurrentSubject).body(request);
1631
1653
  await this.restClient.executeVoid(req);
1632
1654
  }
1633
1655
  async restoreDefaultCertificatesLimit() {
1656
+ this.ensureTestEnvironment();
1634
1657
  const req = RestRequest.delete(Routes.TestData.restoreDefaultCertificatesLimitInCurrentSubject);
1635
1658
  await this.restClient.executeVoid(req);
1636
1659
  }
1637
1660
  // Rate limits
1638
1661
  async setRateLimits(request) {
1662
+ this.ensureTestEnvironment();
1639
1663
  const req = RestRequest.post(Routes.TestData.rateLimits).body(request);
1640
1664
  await this.restClient.executeVoid(req);
1641
1665
  }
1642
1666
  async restoreDefaultRateLimits() {
1667
+ this.ensureTestEnvironment();
1643
1668
  const req = RestRequest.delete(Routes.TestData.rateLimits);
1644
1669
  await this.restClient.executeVoid(req);
1645
1670
  }
1646
1671
  async setProductionRateLimits() {
1672
+ this.ensureTestEnvironment();
1647
1673
  const req = RestRequest.post(Routes.TestData.productionRateLimits);
1648
1674
  await this.restClient.executeVoid(req);
1649
1675
  }
1650
1676
  // Context blocking
1651
1677
  async blockContext(request) {
1678
+ this.ensureTestEnvironment();
1652
1679
  const req = RestRequest.post(Routes.TestData.blockContext).body(request);
1653
1680
  await this.restClient.executeVoid(req);
1654
1681
  }
1655
1682
  async unblockContext(request) {
1683
+ this.ensureTestEnvironment();
1656
1684
  const req = RestRequest.post(Routes.TestData.unblockContext).body(request);
1657
1685
  await this.restClient.executeVoid(req);
1658
1686
  }
@@ -1730,7 +1758,7 @@ ${lines.join("\n")}
1730
1758
 
1731
1759
  // src/crypto/cryptography-service.ts
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 = [];
@@ -1754,11 +1782,11 @@ function pemEncode(der, label) {
1754
1782
  ${lines.join("\n")}
1755
1783
  -----END ${label}-----`;
1756
1784
  }
1757
- var crypto, x509, CryptographyService;
1785
+ var crypto2, x509, CryptographyService;
1758
1786
  var init_cryptography_service = __esm({
1759
1787
  "src/crypto/cryptography-service.ts"() {
1760
1788
  "use strict";
1761
- crypto = __toESM(require("crypto"), 1);
1789
+ crypto2 = __toESM(require("crypto"), 1);
1762
1790
  x509 = __toESM(require("@peculiar/x509"), 1);
1763
1791
  CryptographyService = class {
1764
1792
  fetcher;
@@ -1774,12 +1802,12 @@ var init_cryptography_service = __esm({
1774
1802
  // ---------------------------------------------------------------------------
1775
1803
  /** Encrypt with AES-256-CBC (PKCS7 padding is automatic in Node). */
1776
1804
  encryptAES256(content, key, iv) {
1777
- const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
1805
+ const cipher = crypto2.createCipheriv("aes-256-cbc", key, iv);
1778
1806
  return new Uint8Array(Buffer.concat([cipher.update(content), cipher.final()]));
1779
1807
  }
1780
1808
  /** Decrypt with AES-256-CBC. */
1781
1809
  decryptAES256(content, key, iv) {
1782
- const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
1810
+ const decipher = crypto2.createDecipheriv("aes-256-cbc", key, iv);
1783
1811
  return new Uint8Array(Buffer.concat([decipher.update(content), decipher.final()]));
1784
1812
  }
1785
1813
  // ---------------------------------------------------------------------------
@@ -1790,14 +1818,14 @@ var init_cryptography_service = __esm({
1790
1818
  * SymmetricKeyEncryption certificate's RSA public key (RSA-OAEP SHA-256).
1791
1819
  */
1792
1820
  getEncryptionData() {
1793
- const key = crypto.randomBytes(32);
1794
- const iv = crypto.randomBytes(16);
1821
+ const key = crypto2.randomBytes(32);
1822
+ const iv = crypto2.randomBytes(16);
1795
1823
  const certPem = this.fetcher.getSymmetricKeyEncryptionPem();
1796
- const encryptedKey = crypto.publicEncrypt(
1824
+ const encryptedKey = crypto2.publicEncrypt(
1797
1825
  {
1798
1826
  key: certPem,
1799
1827
  oaepHash: "sha256",
1800
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
1828
+ padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
1801
1829
  },
1802
1830
  key
1803
1831
  );
@@ -1831,7 +1859,7 @@ var init_cryptography_service = __esm({
1831
1859
  const timestampMs = new Date(challengeTimestamp).getTime();
1832
1860
  const plaintext = Buffer.from(`${token}|${timestampMs}`, "utf-8");
1833
1861
  const certPem = this.fetcher.getKsefTokenEncryptionPem();
1834
- const cert = new crypto.X509Certificate(certPem);
1862
+ const cert = new crypto2.X509Certificate(certPem);
1835
1863
  const publicKey = cert.publicKey;
1836
1864
  if (publicKey.asymmetricKeyType === "rsa") {
1837
1865
  return this.encryptRsaOaep(certPem, plaintext);
@@ -1846,7 +1874,7 @@ var init_cryptography_service = __esm({
1846
1874
  // ---------------------------------------------------------------------------
1847
1875
  /** Compute SHA-256 hash (base64) and byte length. */
1848
1876
  getFileMetadata(file) {
1849
- const hash = crypto.createHash("sha256").update(file).digest("base64");
1877
+ const hash = crypto2.createHash("sha256").update(file).digest("base64");
1850
1878
  return { hashSHA: hash, fileSize: file.length };
1851
1879
  }
1852
1880
  // ---------------------------------------------------------------------------
@@ -1861,7 +1889,7 @@ var init_cryptography_service = __esm({
1861
1889
  publicExponent: new Uint8Array([1, 0, 1]),
1862
1890
  modulusLength: 2048
1863
1891
  };
1864
- const keys = await crypto.webcrypto.subtle.generateKey(
1892
+ const keys = await crypto2.webcrypto.subtle.generateKey(
1865
1893
  algorithm,
1866
1894
  true,
1867
1895
  ["sign", "verify"]
@@ -1872,7 +1900,7 @@ var init_cryptography_service = __esm({
1872
1900
  signingAlgorithm: algorithm
1873
1901
  });
1874
1902
  const csrDer = new Uint8Array(csr.rawData);
1875
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1903
+ const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1876
1904
  const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
1877
1905
  return { csrDer, privateKeyPem };
1878
1906
  }
@@ -1883,7 +1911,7 @@ var init_cryptography_service = __esm({
1883
1911
  name: "ECDSA",
1884
1912
  namedCurve: "P-256"
1885
1913
  };
1886
- const keys = await crypto.webcrypto.subtle.generateKey(
1914
+ const keys = await crypto2.webcrypto.subtle.generateKey(
1887
1915
  algorithm,
1888
1916
  true,
1889
1917
  ["sign", "verify"]
@@ -1894,7 +1922,7 @@ var init_cryptography_service = __esm({
1894
1922
  signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
1895
1923
  });
1896
1924
  const csrDer = new Uint8Array(csr.rawData);
1897
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1925
+ const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1898
1926
  const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
1899
1927
  return { csrDer, privateKeyPem };
1900
1928
  }
@@ -1903,7 +1931,7 @@ var init_cryptography_service = __esm({
1903
1931
  // ---------------------------------------------------------------------------
1904
1932
  /** Parse a PEM-encoded private key into a Node.js KeyObject. */
1905
1933
  parsePrivateKey(pem) {
1906
- return crypto.createPrivateKey(pem);
1934
+ return crypto2.createPrivateKey(pem);
1907
1935
  }
1908
1936
  // ---------------------------------------------------------------------------
1909
1937
  // Private helpers
@@ -1911,11 +1939,11 @@ var init_cryptography_service = __esm({
1911
1939
  /** RSA-OAEP SHA-256 encryption. */
1912
1940
  encryptRsaOaep(certPem, plaintext) {
1913
1941
  return new Uint8Array(
1914
- crypto.publicEncrypt(
1942
+ crypto2.publicEncrypt(
1915
1943
  {
1916
1944
  key: certPem,
1917
1945
  oaepHash: "sha256",
1918
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
1946
+ padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
1919
1947
  },
1920
1948
  plaintext
1921
1949
  )
@@ -1932,15 +1960,15 @@ var init_cryptography_service = __esm({
1932
1960
  * (Java-compatible — GCM appends the 16-byte tag to the ciphertext).
1933
1961
  */
1934
1962
  encryptEcdhAesGcm(receiverPublicKey, plaintext) {
1935
- const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto.generateKeyPairSync("ec", {
1963
+ const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto2.generateKeyPairSync("ec", {
1936
1964
  namedCurve: "prime256v1"
1937
1965
  });
1938
- const sharedSecret = crypto.diffieHellman({
1966
+ const sharedSecret = crypto2.diffieHellman({
1939
1967
  privateKey: ephPrivKey,
1940
1968
  publicKey: receiverPublicKey
1941
1969
  });
1942
- const nonce = crypto.randomBytes(12);
1943
- const cipher = crypto.createCipheriv("aes-256-gcm", sharedSecret, nonce);
1970
+ const nonce = crypto2.randomBytes(12);
1971
+ const cipher = crypto2.createCipheriv("aes-256-gcm", sharedSecret, nonce);
1944
1972
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1945
1973
  const tag = cipher.getAuthTag();
1946
1974
  const ephemeralSpki = ephPubKey.export({ type: "spki", format: "der" });
@@ -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
  }
@@ -6623,11 +6651,11 @@ function wrapBase64(base64) {
6623
6651
  }
6624
6652
  return lines.join("\n");
6625
6653
  }
6626
- var crypto2, import_xml_crypto, import_xmldom, XADES_NS, DS_NS, SIGNED_PROPERTIES_TYPE, SHA256_DIGEST_METHOD, EXC_C14N_ALGORITHM, ENVELOPED_SIGNATURE_TRANSFORM, RSA_SHA256_SIGNATURE, ECDSA_SHA256_SIGNATURE, CLOCK_SKEW_BUFFER_MS, SIGNATURE_ID, SIGNED_PROPERTIES_ID, SignatureService;
6654
+ var crypto3, import_xml_crypto, import_xmldom, XADES_NS, DS_NS, SIGNED_PROPERTIES_TYPE, SHA256_DIGEST_METHOD, EXC_C14N_ALGORITHM, ENVELOPED_SIGNATURE_TRANSFORM, RSA_SHA256_SIGNATURE, ECDSA_SHA256_SIGNATURE, CLOCK_SKEW_BUFFER_MS, SIGNATURE_ID, SIGNED_PROPERTIES_ID, SignatureService;
6627
6655
  var init_signature_service = __esm({
6628
6656
  "src/crypto/signature-service.ts"() {
6629
6657
  "use strict";
6630
- crypto2 = __toESM(require("crypto"), 1);
6658
+ crypto3 = __toESM(require("crypto"), 1);
6631
6659
  import_xml_crypto = require("xml-crypto");
6632
6660
  import_xmldom = __toESM(require_lib(), 1);
6633
6661
  XADES_NS = "http://uri.etsi.org/01903/v1.3.2#";
@@ -6656,11 +6684,11 @@ var init_signature_service = __esm({
6656
6684
  }
6657
6685
  const certDer = extractDerFromPem(certPem);
6658
6686
  const certBase64 = certDer.toString("base64");
6659
- const certDigest = crypto2.createHash("sha256").update(certDer).digest("base64");
6660
- const x5093 = new crypto2.X509Certificate(certPem);
6687
+ const certDigest = crypto3.createHash("sha256").update(certDer).digest("base64");
6688
+ const x5093 = new crypto3.X509Certificate(certPem);
6661
6689
  const issuerName = normalizeIssuerDn(x5093.issuer);
6662
6690
  const serialNumber = hexSerialToDecimal(x5093.serialNumber);
6663
- const privateKey = crypto2.createPrivateKey(privateKeyPem);
6691
+ const privateKey = crypto3.createPrivateKey(privateKeyPem);
6664
6692
  const isEc = privateKey.asymmetricKeyType === "ec";
6665
6693
  const signatureAlgorithm = isEc ? ECDSA_SHA256_SIGNATURE : RSA_SHA256_SIGNATURE;
6666
6694
  const signingTime = new Date(Date.now() + CLOCK_SKEW_BUFFER_MS).toISOString();
@@ -6935,7 +6963,7 @@ var init_client = __esm({
6935
6963
  this.lighthouse = new LighthouseService(this.options);
6936
6964
  this.limits = new LimitsService(restClient);
6937
6965
  this.peppol = new PeppolService(restClient);
6938
- this.testData = new TestDataService(restClient);
6966
+ this.testData = new TestDataService(restClient, this.options.environmentName);
6939
6967
  this.qr = new VerificationLinkService(this.options.baseQrUrl);
6940
6968
  }
6941
6969
  async loginWithToken(token, nip) {
@@ -6997,7 +7025,11 @@ __export(index_exports, {
6997
7025
  AuthService: () => AuthService,
6998
7026
  AuthTokenRequestBuilder: () => AuthTokenRequestBuilder,
6999
7027
  AuthorizationPermissionGrantBuilder: () => AuthorizationPermissionGrantBuilder,
7028
+ BATCH_MAX_PARTS: () => BATCH_MAX_PARTS,
7029
+ BATCH_MAX_PART_SIZE: () => BATCH_MAX_PART_SIZE,
7030
+ BATCH_MAX_TOTAL_SIZE: () => BATCH_MAX_TOTAL_SIZE,
7000
7031
  Base64String: () => Base64String,
7032
+ BatchFileBuilder: () => BatchFileBuilder,
7001
7033
  BatchSessionService: () => BatchSessionService,
7002
7034
  CERTIFICATE_NAME_MAX_LENGTH: () => CERTIFICATE_NAME_MAX_LENGTH,
7003
7035
  CERTIFICATE_NAME_MIN_LENGTH: () => CERTIFICATE_NAME_MIN_LENGTH,
@@ -7590,18 +7622,86 @@ var AuthorizationPermissionGrantBuilder = class {
7590
7622
  }
7591
7623
  };
7592
7624
 
7625
+ // src/builders/batch-file.ts
7626
+ var crypto = __toESM(require("crypto"), 1);
7627
+ init_ksef_validation_error();
7628
+ var BATCH_MAX_PART_SIZE = 1e8;
7629
+ var BATCH_MAX_TOTAL_SIZE = 5e9;
7630
+ var BATCH_MAX_PARTS = 50;
7631
+ var BatchFileBuilder = class {
7632
+ /**
7633
+ * Build batch file metadata and encrypted parts from a raw ZIP.
7634
+ *
7635
+ * @param zipBytes - Unencrypted ZIP data
7636
+ * @param encryptFn - AES-256-CBC encryption function (called per part)
7637
+ * @param options - Optional configuration
7638
+ */
7639
+ static build(zipBytes, encryptFn, options) {
7640
+ const maxPartSize = options?.maxPartSize ?? BATCH_MAX_PART_SIZE;
7641
+ if (maxPartSize <= 0) {
7642
+ throw new KSeFValidationError("maxPartSize must be a positive number");
7643
+ }
7644
+ if (zipBytes.length === 0) {
7645
+ throw new KSeFValidationError("ZIP data must not be empty");
7646
+ }
7647
+ if (zipBytes.length > BATCH_MAX_TOTAL_SIZE) {
7648
+ throw new KSeFValidationError(
7649
+ `ZIP size ${zipBytes.length} exceeds maximum of ${BATCH_MAX_TOTAL_SIZE} bytes (5 GB)`
7650
+ );
7651
+ }
7652
+ const rawParts = splitBuffer(zipBytes, maxPartSize);
7653
+ if (rawParts.length > BATCH_MAX_PARTS) {
7654
+ throw new KSeFValidationError(
7655
+ `Data requires ${rawParts.length} parts, exceeding maximum of ${BATCH_MAX_PARTS}`
7656
+ );
7657
+ }
7658
+ const zipHash = sha256Base64(zipBytes);
7659
+ const encryptedParts = [];
7660
+ const fileParts = rawParts.map((raw, i) => {
7661
+ const encrypted = encryptFn(raw);
7662
+ encryptedParts.push(encrypted);
7663
+ return {
7664
+ ordinalNumber: i + 1,
7665
+ fileSize: encrypted.length,
7666
+ fileHash: sha256Base64(encrypted)
7667
+ };
7668
+ });
7669
+ return {
7670
+ batchFile: {
7671
+ fileSize: zipBytes.length,
7672
+ fileHash: zipHash,
7673
+ fileParts
7674
+ },
7675
+ encryptedParts
7676
+ };
7677
+ }
7678
+ };
7679
+ function splitBuffer(data, maxPartSize) {
7680
+ if (data.length <= maxPartSize) {
7681
+ return [data];
7682
+ }
7683
+ const parts = [];
7684
+ for (let offset = 0; offset < data.length; offset += maxPartSize) {
7685
+ parts.push(data.subarray(offset, Math.min(offset + maxPartSize, data.length)));
7686
+ }
7687
+ return parts;
7688
+ }
7689
+ function sha256Base64(data) {
7690
+ return crypto.createHash("sha256").update(data).digest("base64");
7691
+ }
7692
+
7593
7693
  // src/crypto/index.ts
7594
7694
  init_certificate_fetcher();
7595
7695
  init_cryptography_service();
7596
7696
  init_signature_service();
7597
7697
 
7598
7698
  // src/crypto/certificate-service.ts
7599
- var crypto3 = __toESM(require("crypto"), 1);
7699
+ var crypto4 = __toESM(require("crypto"), 1);
7600
7700
  var x5092 = __toESM(require("@peculiar/x509"), 1);
7601
7701
  var CertificateService = class {
7602
7702
  static getSha256Fingerprint(certPem) {
7603
7703
  const der = extractDerFromPem2(certPem);
7604
- return crypto3.createHash("sha256").update(der).digest("hex").toUpperCase();
7704
+ return crypto4.createHash("sha256").update(der).digest("hex").toUpperCase();
7605
7705
  }
7606
7706
  static async generatePersonalCertificate(givenName, surname, serialNumber, commonName, method = "RSA") {
7607
7707
  const nameParts = [];
@@ -7624,7 +7724,7 @@ var CertificateService = class {
7624
7724
  }
7625
7725
  };
7626
7726
  async function generateSelfSigned(subject, method) {
7627
- x5092.cryptoProvider.set(crypto3.webcrypto);
7727
+ x5092.cryptoProvider.set(crypto4.webcrypto);
7628
7728
  let algorithm;
7629
7729
  let signingAlgorithm;
7630
7730
  if (method === "ECDSA") {
@@ -7639,7 +7739,7 @@ async function generateSelfSigned(subject, method) {
7639
7739
  };
7640
7740
  signingAlgorithm = algorithm;
7641
7741
  }
7642
- const keys = await crypto3.webcrypto.subtle.generateKey(
7742
+ const keys = await crypto4.webcrypto.subtle.generateKey(
7643
7743
  algorithm,
7644
7744
  true,
7645
7745
  ["sign", "verify"]
@@ -7656,9 +7756,9 @@ async function generateSelfSigned(subject, method) {
7656
7756
  serialNumber: Date.now().toString(16)
7657
7757
  });
7658
7758
  const certPem = cert.toString("pem");
7659
- const pkcs8 = await crypto3.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7759
+ const pkcs8 = await crypto4.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7660
7760
  const privateKeyPem = pemEncode2(new Uint8Array(pkcs8), "PRIVATE KEY");
7661
- const fingerprint = crypto3.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
7761
+ const fingerprint = crypto4.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
7662
7762
  return { certificatePem: certPem, privateKeyPem, fingerprint };
7663
7763
  }
7664
7764
  function extractDerFromPem2(pem) {
@@ -7792,7 +7892,7 @@ async function openOnlineSession(client, options) {
7792
7892
  async waitForUpo(pollOpts) {
7793
7893
  const result = await pollUntil(
7794
7894
  () => client.sessionStatus.getSessionStatus(sessionRef),
7795
- (s) => s.status.code !== 100,
7895
+ (s) => s.status.code === 200 || s.status.code >= 400,
7796
7896
  { ...pollOpts, description: `UPO for session ${sessionRef}` }
7797
7897
  );
7798
7898
  if (result.status.code !== 200) {
@@ -7818,31 +7918,36 @@ async function openSendAndClose(client, invoices, options) {
7818
7918
 
7819
7919
  // src/workflows/batch-session-workflow.ts
7820
7920
  var DEFAULT_FORM_CODE2 = { systemCode: "FA", schemaVersion: "3", value: "FA (3)" };
7821
- async function uploadBatch(client, zipParts, totalFileSize, totalFileHash, options) {
7921
+ async function uploadBatch(client, zipData, options) {
7822
7922
  await client.crypto.init();
7823
7923
  const encData = client.crypto.getEncryptionData();
7824
7924
  const formCode = options?.formCode ?? DEFAULT_FORM_CODE2;
7825
- const fileParts = zipParts.map((part, i) => {
7826
- const meta = client.crypto.getFileMetadata(new Uint8Array(part.data));
7827
- return { ordinalNumber: i + 1, fileSize: meta.fileSize, fileHash: meta.hashSHA };
7925
+ const encryptFn = (part) => client.crypto.encryptAES256(part, encData.cipherKey, encData.cipherIv);
7926
+ const { batchFile, encryptedParts } = BatchFileBuilder.build(zipData, encryptFn, {
7927
+ maxPartSize: options?.maxPartSize
7828
7928
  });
7829
7929
  const openResp = await client.batchSession.openSession(
7830
7930
  {
7831
7931
  formCode,
7832
7932
  encryption: encData.encryptionInfo,
7833
- batchFile: { fileSize: totalFileSize, fileHash: totalFileHash, fileParts }
7933
+ batchFile,
7934
+ offlineMode: options?.offlineMode
7834
7935
  },
7835
7936
  options?.upoVersion
7836
7937
  );
7837
- const sendingParts = zipParts.map((part, i) => {
7838
- const meta = client.crypto.getFileMetadata(new Uint8Array(part.data));
7839
- return { data: part.data, metadata: meta, ordinalNumber: i + 1 };
7840
- });
7938
+ const sendingParts = encryptedParts.map((part, i) => ({
7939
+ data: part.buffer.slice(part.byteOffset, part.byteOffset + part.byteLength),
7940
+ metadata: {
7941
+ hashSHA: batchFile.fileParts[i].fileHash,
7942
+ fileSize: batchFile.fileParts[i].fileSize
7943
+ },
7944
+ ordinalNumber: i + 1
7945
+ }));
7841
7946
  await client.batchSession.sendParts(openResp, sendingParts);
7842
7947
  await client.batchSession.closeSession(openResp.referenceNumber);
7843
7948
  const result = await pollUntil(
7844
7949
  () => client.sessionStatus.getSessionStatus(openResp.referenceNumber),
7845
- (s) => s.status.code !== 100,
7950
+ (s) => s.status.code === 200 || s.status.code >= 400,
7846
7951
  { ...options?.pollOptions, description: `UPO for batch ${openResp.referenceNumber}` }
7847
7952
  );
7848
7953
  if (result.status.code !== 200) {
@@ -7860,7 +7965,7 @@ async function uploadBatch(client, zipParts, totalFileSize, totalFileHash, optio
7860
7965
  }
7861
7966
 
7862
7967
  // src/workflows/invoice-export-workflow.ts
7863
- async function exportInvoices(client, filters, options) {
7968
+ async function doExport(client, filters, options) {
7864
7969
  await client.crypto.init();
7865
7970
  const encData = client.crypto.getEncryptionData();
7866
7971
  const opResp = await client.invoices.exportInvoices({
@@ -7870,7 +7975,7 @@ async function exportInvoices(client, filters, options) {
7870
7975
  });
7871
7976
  const result = await pollUntil(
7872
7977
  () => client.invoices.getInvoiceExportStatus(opResp.referenceNumber),
7873
- (s) => s.status.code !== 100,
7978
+ (s) => s.status.code === 200 || s.status.code >= 400,
7874
7979
  { ...options?.pollOptions, description: `export ${opResp.referenceNumber}` }
7875
7980
  );
7876
7981
  if (result.status.code !== 200) {
@@ -7880,23 +7985,29 @@ async function exportInvoices(client, filters, options) {
7880
7985
  throw new Error("Export completed but no package available");
7881
7986
  }
7882
7987
  return {
7883
- parts: result.package.parts.map((p) => ({
7884
- ordinalNumber: p.ordinalNumber,
7885
- url: p.url,
7886
- method: p.method,
7887
- partSize: p.partSize,
7888
- encryptedPartSize: p.encryptedPartSize,
7889
- encryptedPartHash: p.encryptedPartHash,
7890
- expirationDate: p.expirationDate
7891
- })),
7892
- invoiceCount: result.package.invoiceCount,
7893
- isTruncated: result.package.isTruncated,
7894
- permanentStorageHwmDate: result.package.permanentStorageHwmDate
7988
+ encData,
7989
+ result: {
7990
+ parts: result.package.parts.map((p) => ({
7991
+ ordinalNumber: p.ordinalNumber,
7992
+ url: p.url,
7993
+ method: p.method,
7994
+ partSize: p.partSize,
7995
+ encryptedPartSize: p.encryptedPartSize,
7996
+ encryptedPartHash: p.encryptedPartHash,
7997
+ expirationDate: p.expirationDate
7998
+ })),
7999
+ invoiceCount: result.package.invoiceCount,
8000
+ isTruncated: result.package.isTruncated,
8001
+ permanentStorageHwmDate: result.package.permanentStorageHwmDate
8002
+ }
7895
8003
  };
7896
8004
  }
8005
+ async function exportInvoices(client, filters, options) {
8006
+ const { result } = await doExport(client, filters, options);
8007
+ return result;
8008
+ }
7897
8009
  async function exportAndDownload(client, filters, options) {
7898
- const encData = client.crypto.getEncryptionData();
7899
- const exportResult = await exportInvoices(client, filters, options);
8010
+ const { result: exportResult, encData } = await doExport(client, filters, options);
7900
8011
  const download = options?.transport ?? fetch;
7901
8012
  const decryptedParts = [];
7902
8013
  for (const part of exportResult.parts) {
@@ -7990,7 +8101,11 @@ init_client();
7990
8101
  AuthService,
7991
8102
  AuthTokenRequestBuilder,
7992
8103
  AuthorizationPermissionGrantBuilder,
8104
+ BATCH_MAX_PARTS,
8105
+ BATCH_MAX_PART_SIZE,
8106
+ BATCH_MAX_TOTAL_SIZE,
7993
8107
  Base64String,
8108
+ BatchFileBuilder,
7994
8109
  BatchSessionService,
7995
8110
  CERTIFICATE_NAME_MAX_LENGTH,
7996
8111
  CERTIFICATE_NAME_MIN_LENGTH,