ksef-client-ts 0.2.0 → 0.4.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;
@@ -1105,6 +1106,36 @@ var init_batch_session = __esm({
1105
1106
  });
1106
1107
  await Promise.all(tasks);
1107
1108
  }
1109
+ /**
1110
+ * Upload parts sequentially (not in parallel) because each part uses a
1111
+ * streaming body (`duplex: 'half'`). Parallel streaming uploads can cause
1112
+ * backpressure issues and exceed memory limits for large payloads.
1113
+ */
1114
+ async sendPartsWithStream(openResponse, parts) {
1115
+ const uploadRequests = openResponse.partUploadRequests;
1116
+ for (const part of parts) {
1117
+ const uploadReq = uploadRequests.find(
1118
+ (r) => r.ordinalNumber === part.ordinalNumber
1119
+ );
1120
+ if (!uploadReq) {
1121
+ throw new Error(`No upload request found for part ${part.ordinalNumber}`);
1122
+ }
1123
+ const headers = {};
1124
+ for (const [k, v] of Object.entries(uploadReq.headers)) {
1125
+ if (v != null) headers[k] = v;
1126
+ }
1127
+ const resp = await fetch(uploadReq.url, {
1128
+ method: uploadReq.method,
1129
+ headers,
1130
+ body: part.dataStream,
1131
+ // @ts-expect-error -- Node 18+ undici supports duplex for streaming body
1132
+ duplex: "half"
1133
+ });
1134
+ if (!resp.ok) {
1135
+ throw new Error(`Upload failed for part ${part.ordinalNumber}: HTTP ${resp.status}`);
1136
+ }
1137
+ }
1138
+ }
1108
1139
  async closeSession(batchRef) {
1109
1140
  const req = RestRequest.post(Routes.Sessions.Batch.close(batchRef));
1110
1141
  await this.restClient.executeVoid(req);
@@ -1573,84 +1604,111 @@ var init_test_data = __esm({
1573
1604
  "use strict";
1574
1605
  init_rest_request();
1575
1606
  init_routes();
1607
+ init_ksef_error();
1576
1608
  TestDataService = class {
1577
1609
  restClient;
1578
- constructor(restClient) {
1610
+ environmentName;
1611
+ constructor(restClient, environmentName) {
1579
1612
  this.restClient = restClient;
1613
+ this.environmentName = environmentName;
1614
+ }
1615
+ ensureTestEnvironment() {
1616
+ if (this.environmentName && this.environmentName !== "TEST") {
1617
+ throw new KSeFError(
1618
+ `Test data APIs are only available on the TEST environment (current: ${this.environmentName})`
1619
+ );
1620
+ }
1580
1621
  }
1581
1622
  // Subject management
1582
1623
  async createSubject(request) {
1624
+ this.ensureTestEnvironment();
1583
1625
  const req = RestRequest.post(Routes.TestData.createSubject).body(request);
1584
1626
  await this.restClient.executeVoid(req);
1585
1627
  }
1586
1628
  async removeSubject(request) {
1629
+ this.ensureTestEnvironment();
1587
1630
  const req = RestRequest.post(Routes.TestData.removeSubject).body(request);
1588
1631
  await this.restClient.executeVoid(req);
1589
1632
  }
1590
1633
  // Person management
1591
1634
  async createPerson(request) {
1635
+ this.ensureTestEnvironment();
1592
1636
  const req = RestRequest.post(Routes.TestData.createPerson).body(request);
1593
1637
  await this.restClient.executeVoid(req);
1594
1638
  }
1595
1639
  async removePerson(request) {
1640
+ this.ensureTestEnvironment();
1596
1641
  const req = RestRequest.post(Routes.TestData.removePerson).body(request);
1597
1642
  await this.restClient.executeVoid(req);
1598
1643
  }
1599
1644
  // Permissions
1600
1645
  async grantPermissions(request) {
1646
+ this.ensureTestEnvironment();
1601
1647
  const req = RestRequest.post(Routes.TestData.grantPerms).body(request);
1602
1648
  await this.restClient.executeVoid(req);
1603
1649
  }
1604
1650
  async revokePermissions(request) {
1651
+ this.ensureTestEnvironment();
1605
1652
  const req = RestRequest.post(Routes.TestData.revokePerms).body(request);
1606
1653
  await this.restClient.executeVoid(req);
1607
1654
  }
1608
1655
  // Attachment permissions
1609
1656
  async enableAttachment(request) {
1657
+ this.ensureTestEnvironment();
1610
1658
  const req = RestRequest.post(Routes.TestData.enableAttach).body(request);
1611
1659
  await this.restClient.executeVoid(req);
1612
1660
  }
1613
1661
  async disableAttachment(request) {
1662
+ this.ensureTestEnvironment();
1614
1663
  const req = RestRequest.post(Routes.TestData.disableAttach).body(request);
1615
1664
  await this.restClient.executeVoid(req);
1616
1665
  }
1617
1666
  // Session limits
1618
1667
  async changeSessionLimits(request) {
1668
+ this.ensureTestEnvironment();
1619
1669
  const req = RestRequest.post(Routes.TestData.changeSessionLimitsInCurrentContext).body(request);
1620
1670
  await this.restClient.executeVoid(req);
1621
1671
  }
1622
1672
  async restoreDefaultSessionLimits() {
1673
+ this.ensureTestEnvironment();
1623
1674
  const req = RestRequest.delete(Routes.TestData.restoreDefaultSessionLimitsInCurrentContext);
1624
1675
  await this.restClient.executeVoid(req);
1625
1676
  }
1626
1677
  // Certificate limits
1627
1678
  async changeCertificatesLimit(request) {
1679
+ this.ensureTestEnvironment();
1628
1680
  const req = RestRequest.post(Routes.TestData.changeCertificatesLimitInCurrentSubject).body(request);
1629
1681
  await this.restClient.executeVoid(req);
1630
1682
  }
1631
1683
  async restoreDefaultCertificatesLimit() {
1684
+ this.ensureTestEnvironment();
1632
1685
  const req = RestRequest.delete(Routes.TestData.restoreDefaultCertificatesLimitInCurrentSubject);
1633
1686
  await this.restClient.executeVoid(req);
1634
1687
  }
1635
1688
  // Rate limits
1636
1689
  async setRateLimits(request) {
1690
+ this.ensureTestEnvironment();
1637
1691
  const req = RestRequest.post(Routes.TestData.rateLimits).body(request);
1638
1692
  await this.restClient.executeVoid(req);
1639
1693
  }
1640
1694
  async restoreDefaultRateLimits() {
1695
+ this.ensureTestEnvironment();
1641
1696
  const req = RestRequest.delete(Routes.TestData.rateLimits);
1642
1697
  await this.restClient.executeVoid(req);
1643
1698
  }
1644
1699
  async setProductionRateLimits() {
1700
+ this.ensureTestEnvironment();
1645
1701
  const req = RestRequest.post(Routes.TestData.productionRateLimits);
1646
1702
  await this.restClient.executeVoid(req);
1647
1703
  }
1648
1704
  // Context blocking
1649
1705
  async blockContext(request) {
1706
+ this.ensureTestEnvironment();
1650
1707
  const req = RestRequest.post(Routes.TestData.blockContext).body(request);
1651
1708
  await this.restClient.executeVoid(req);
1652
1709
  }
1653
1710
  async unblockContext(request) {
1711
+ this.ensureTestEnvironment();
1654
1712
  const req = RestRequest.post(Routes.TestData.unblockContext).body(request);
1655
1713
  await this.restClient.executeVoid(req);
1656
1714
  }
@@ -1727,10 +1785,10 @@ ${lines.join("\n")}
1727
1785
  });
1728
1786
 
1729
1787
  // src/crypto/cryptography-service.ts
1730
- import * as crypto from "crypto";
1788
+ import * as crypto2 from "crypto";
1731
1789
  import * as x509 from "@peculiar/x509";
1732
1790
  function setCryptoProvider() {
1733
- x509.cryptoProvider.set(crypto.webcrypto);
1791
+ x509.cryptoProvider.set(crypto2.webcrypto);
1734
1792
  }
1735
1793
  function buildX500Name(fields) {
1736
1794
  const parts = [];
@@ -1772,12 +1830,34 @@ var init_cryptography_service = __esm({
1772
1830
  // ---------------------------------------------------------------------------
1773
1831
  /** Encrypt with AES-256-CBC (PKCS7 padding is automatic in Node). */
1774
1832
  encryptAES256(content, key, iv) {
1775
- const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
1833
+ const cipher = crypto2.createCipheriv("aes-256-cbc", key, iv);
1776
1834
  return new Uint8Array(Buffer.concat([cipher.update(content), cipher.final()]));
1777
1835
  }
1836
+ /**
1837
+ * Encrypt with AES-256-CBC as a streaming transform.
1838
+ * Returns a ReadableStream that yields encrypted chunks as the input is read.
1839
+ */
1840
+ encryptAES256Stream(input, key, iv) {
1841
+ const cipher = crypto2.createCipheriv("aes-256-cbc", key, iv);
1842
+ const transform = new TransformStream({
1843
+ transform(chunk, controller) {
1844
+ const encrypted = cipher.update(chunk);
1845
+ if (encrypted.length > 0) {
1846
+ controller.enqueue(new Uint8Array(encrypted));
1847
+ }
1848
+ },
1849
+ flush(controller) {
1850
+ const final = cipher.final();
1851
+ if (final.length > 0) {
1852
+ controller.enqueue(new Uint8Array(final));
1853
+ }
1854
+ }
1855
+ });
1856
+ return input.pipeThrough(transform);
1857
+ }
1778
1858
  /** Decrypt with AES-256-CBC. */
1779
1859
  decryptAES256(content, key, iv) {
1780
- const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
1860
+ const decipher = crypto2.createDecipheriv("aes-256-cbc", key, iv);
1781
1861
  return new Uint8Array(Buffer.concat([decipher.update(content), decipher.final()]));
1782
1862
  }
1783
1863
  // ---------------------------------------------------------------------------
@@ -1788,14 +1868,14 @@ var init_cryptography_service = __esm({
1788
1868
  * SymmetricKeyEncryption certificate's RSA public key (RSA-OAEP SHA-256).
1789
1869
  */
1790
1870
  getEncryptionData() {
1791
- const key = crypto.randomBytes(32);
1792
- const iv = crypto.randomBytes(16);
1871
+ const key = crypto2.randomBytes(32);
1872
+ const iv = crypto2.randomBytes(16);
1793
1873
  const certPem = this.fetcher.getSymmetricKeyEncryptionPem();
1794
- const encryptedKey = crypto.publicEncrypt(
1874
+ const encryptedKey = crypto2.publicEncrypt(
1795
1875
  {
1796
1876
  key: certPem,
1797
1877
  oaepHash: "sha256",
1798
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
1878
+ padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
1799
1879
  },
1800
1880
  key
1801
1881
  );
@@ -1829,7 +1909,7 @@ var init_cryptography_service = __esm({
1829
1909
  const timestampMs = new Date(challengeTimestamp).getTime();
1830
1910
  const plaintext = Buffer.from(`${token}|${timestampMs}`, "utf-8");
1831
1911
  const certPem = this.fetcher.getKsefTokenEncryptionPem();
1832
- const cert = new crypto.X509Certificate(certPem);
1912
+ const cert = new crypto2.X509Certificate(certPem);
1833
1913
  const publicKey = cert.publicKey;
1834
1914
  if (publicKey.asymmetricKeyType === "rsa") {
1835
1915
  return this.encryptRsaOaep(certPem, plaintext);
@@ -1844,9 +1924,26 @@ var init_cryptography_service = __esm({
1844
1924
  // ---------------------------------------------------------------------------
1845
1925
  /** Compute SHA-256 hash (base64) and byte length. */
1846
1926
  getFileMetadata(file) {
1847
- const hash = crypto.createHash("sha256").update(file).digest("base64");
1927
+ const hash = crypto2.createHash("sha256").update(file).digest("base64");
1848
1928
  return { hashSHA: hash, fileSize: file.length };
1849
1929
  }
1930
+ /** Compute SHA-256 hash (base64) and byte length from a ReadableStream. */
1931
+ async getFileMetadataFromStream(stream) {
1932
+ const hash = crypto2.createHash("sha256");
1933
+ let fileSize = 0;
1934
+ const reader = stream.getReader();
1935
+ try {
1936
+ for (; ; ) {
1937
+ const { done, value } = await reader.read();
1938
+ if (done) break;
1939
+ hash.update(value);
1940
+ fileSize += value.byteLength;
1941
+ }
1942
+ } finally {
1943
+ reader.releaseLock();
1944
+ }
1945
+ return { hashSHA: hash.digest("base64"), fileSize };
1946
+ }
1850
1947
  // ---------------------------------------------------------------------------
1851
1948
  // CSR generation
1852
1949
  // ---------------------------------------------------------------------------
@@ -1859,7 +1956,7 @@ var init_cryptography_service = __esm({
1859
1956
  publicExponent: new Uint8Array([1, 0, 1]),
1860
1957
  modulusLength: 2048
1861
1958
  };
1862
- const keys = await crypto.webcrypto.subtle.generateKey(
1959
+ const keys = await crypto2.webcrypto.subtle.generateKey(
1863
1960
  algorithm,
1864
1961
  true,
1865
1962
  ["sign", "verify"]
@@ -1870,7 +1967,7 @@ var init_cryptography_service = __esm({
1870
1967
  signingAlgorithm: algorithm
1871
1968
  });
1872
1969
  const csrDer = new Uint8Array(csr.rawData);
1873
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1970
+ const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1874
1971
  const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
1875
1972
  return { csrDer, privateKeyPem };
1876
1973
  }
@@ -1881,7 +1978,7 @@ var init_cryptography_service = __esm({
1881
1978
  name: "ECDSA",
1882
1979
  namedCurve: "P-256"
1883
1980
  };
1884
- const keys = await crypto.webcrypto.subtle.generateKey(
1981
+ const keys = await crypto2.webcrypto.subtle.generateKey(
1885
1982
  algorithm,
1886
1983
  true,
1887
1984
  ["sign", "verify"]
@@ -1892,7 +1989,7 @@ var init_cryptography_service = __esm({
1892
1989
  signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
1893
1990
  });
1894
1991
  const csrDer = new Uint8Array(csr.rawData);
1895
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1992
+ const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
1896
1993
  const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
1897
1994
  return { csrDer, privateKeyPem };
1898
1995
  }
@@ -1901,7 +1998,7 @@ var init_cryptography_service = __esm({
1901
1998
  // ---------------------------------------------------------------------------
1902
1999
  /** Parse a PEM-encoded private key into a Node.js KeyObject. */
1903
2000
  parsePrivateKey(pem) {
1904
- return crypto.createPrivateKey(pem);
2001
+ return crypto2.createPrivateKey(pem);
1905
2002
  }
1906
2003
  // ---------------------------------------------------------------------------
1907
2004
  // Private helpers
@@ -1909,11 +2006,11 @@ var init_cryptography_service = __esm({
1909
2006
  /** RSA-OAEP SHA-256 encryption. */
1910
2007
  encryptRsaOaep(certPem, plaintext) {
1911
2008
  return new Uint8Array(
1912
- crypto.publicEncrypt(
2009
+ crypto2.publicEncrypt(
1913
2010
  {
1914
2011
  key: certPem,
1915
2012
  oaepHash: "sha256",
1916
- padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
2013
+ padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
1917
2014
  },
1918
2015
  plaintext
1919
2016
  )
@@ -1930,15 +2027,15 @@ var init_cryptography_service = __esm({
1930
2027
  * (Java-compatible — GCM appends the 16-byte tag to the ciphertext).
1931
2028
  */
1932
2029
  encryptEcdhAesGcm(receiverPublicKey, plaintext) {
1933
- const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto.generateKeyPairSync("ec", {
2030
+ const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto2.generateKeyPairSync("ec", {
1934
2031
  namedCurve: "prime256v1"
1935
2032
  });
1936
- const sharedSecret = crypto.diffieHellman({
2033
+ const sharedSecret = crypto2.diffieHellman({
1937
2034
  privateKey: ephPrivKey,
1938
2035
  publicKey: receiverPublicKey
1939
2036
  });
1940
- const nonce = crypto.randomBytes(12);
1941
- const cipher = crypto.createCipheriv("aes-256-gcm", sharedSecret, nonce);
2037
+ const nonce = crypto2.randomBytes(12);
2038
+ const cipher = crypto2.createCipheriv("aes-256-gcm", sharedSecret, nonce);
1942
2039
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1943
2040
  const tag = cipher.getAuthTag();
1944
2041
  const ephemeralSpki = ephPubKey.export({ type: "spki", format: "der" });
@@ -6489,7 +6586,7 @@ var signature_service_exports = {};
6489
6586
  __export(signature_service_exports, {
6490
6587
  SignatureService: () => SignatureService
6491
6588
  });
6492
- import * as crypto2 from "crypto";
6589
+ import * as crypto3 from "crypto";
6493
6590
  import { ExclusiveCanonicalization } from "xml-crypto";
6494
6591
  function extractDerFromPem(pem) {
6495
6592
  const base64 = pem.replace(/-----BEGIN [A-Z\s]+-----/g, "").replace(/-----END [A-Z\s]+-----/g, "").replace(/\s+/g, "");
@@ -6508,7 +6605,7 @@ function canonicalize(elem) {
6508
6605
  function computeRootDigest(doc) {
6509
6606
  const root = doc.documentElement;
6510
6607
  const canonical = canonicalize(root);
6511
- return crypto2.createHash("sha256").update(canonical, "utf-8").digest("base64");
6608
+ return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
6512
6609
  }
6513
6610
  function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
6514
6611
  const parser = new import_xmldom.DOMParser();
@@ -6518,7 +6615,7 @@ function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
6518
6615
  throw new Error("SignedProperties element not found in QualifyingProperties");
6519
6616
  }
6520
6617
  const canonical = canonicalize(signedProps);
6521
- return crypto2.createHash("sha256").update(canonical, "utf-8").digest("base64");
6618
+ return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
6522
6619
  }
6523
6620
  function buildSignedInfo(signatureAlgorithm, rootDigest, signedPropertiesDigest) {
6524
6621
  return [
@@ -6549,12 +6646,12 @@ function computeSignatureValue(canonicalSignedInfo, privateKeyPem, isEc) {
6549
6646
  const data = Buffer.from(canonicalSignedInfo, "utf-8");
6550
6647
  let signature;
6551
6648
  if (isEc) {
6552
- signature = crypto2.sign("sha256", data, {
6649
+ signature = crypto3.sign("sha256", data, {
6553
6650
  key: privateKeyPem,
6554
6651
  dsaEncoding: "ieee-p1363"
6555
6652
  });
6556
6653
  } else {
6557
- signature = crypto2.sign("sha256", data, privateKeyPem);
6654
+ signature = crypto3.sign("sha256", data, privateKeyPem);
6558
6655
  }
6559
6656
  return signature.toString("base64");
6560
6657
  }
@@ -6654,11 +6751,11 @@ var init_signature_service = __esm({
6654
6751
  }
6655
6752
  const certDer = extractDerFromPem(certPem);
6656
6753
  const certBase64 = certDer.toString("base64");
6657
- const certDigest = crypto2.createHash("sha256").update(certDer).digest("base64");
6658
- const x5093 = new crypto2.X509Certificate(certPem);
6754
+ const certDigest = crypto3.createHash("sha256").update(certDer).digest("base64");
6755
+ const x5093 = new crypto3.X509Certificate(certPem);
6659
6756
  const issuerName = normalizeIssuerDn(x5093.issuer);
6660
6757
  const serialNumber = hexSerialToDecimal(x5093.serialNumber);
6661
- const privateKey = crypto2.createPrivateKey(privateKeyPem);
6758
+ const privateKey = crypto3.createPrivateKey(privateKeyPem);
6662
6759
  const isEc = privateKey.asymmetricKeyType === "ec";
6663
6760
  const signatureAlgorithm = isEc ? ECDSA_SHA256_SIGNATURE : RSA_SHA256_SIGNATURE;
6664
6761
  const signingTime = new Date(Date.now() + CLOCK_SKEW_BUFFER_MS).toISOString();
@@ -6761,8 +6858,34 @@ var init_pkcs12_loader = __esm({
6761
6858
  }
6762
6859
  });
6763
6860
 
6861
+ // src/crypto/auth-xml-builder.ts
6862
+ function buildUnsignedAuthTokenRequestXml(options) {
6863
+ const { challenge, contextIdentifier, subjectIdentifierType = "certificateSubject" } = options;
6864
+ const identifierElement = `<${contextIdentifier.type}>${xmlEscape(contextIdentifier.value)}</${contextIdentifier.type}>`;
6865
+ return [
6866
+ '<?xml version="1.0" encoding="utf-8"?>',
6867
+ `<AuthTokenRequest xmlns="${AUTH_TOKEN_REQUEST_NS}">`,
6868
+ `<Challenge>${xmlEscape(challenge)}</Challenge>`,
6869
+ `<ContextIdentifier>`,
6870
+ identifierElement,
6871
+ `</ContextIdentifier>`,
6872
+ `<SubjectIdentifierType>${xmlEscape(subjectIdentifierType)}</SubjectIdentifierType>`,
6873
+ `</AuthTokenRequest>`
6874
+ ].join("");
6875
+ }
6876
+ function xmlEscape(str) {
6877
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
6878
+ }
6879
+ var AUTH_TOKEN_REQUEST_NS;
6880
+ var init_auth_xml_builder = __esm({
6881
+ "src/crypto/auth-xml-builder.ts"() {
6882
+ "use strict";
6883
+ AUTH_TOKEN_REQUEST_NS = "http://ksef.mf.gov.pl/auth/token/2.0";
6884
+ }
6885
+ });
6886
+
6764
6887
  // src/qr/verification-link-service.ts
6765
- import crypto4 from "crypto";
6888
+ import crypto5 from "crypto";
6766
6889
  var VerificationLinkService;
6767
6890
  var init_verification_link_service = __esm({
6768
6891
  "src/qr/verification-link-service.ts"() {
@@ -6792,16 +6915,16 @@ var init_verification_link_service = __esm({
6792
6915
  const hashBase64Url = this.base64ToBase64Url(invoiceHashBase64);
6793
6916
  const pathWithoutSignature = `${this.baseQrUrl}/certificate/${contextType}/${contextId}/${sellerNip}/${certSerial}/${hashBase64Url}`;
6794
6917
  const dataToSign = pathWithoutSignature.replace(/^https?:\/\//, "");
6795
- const key = crypto4.createPrivateKey(privateKeyPem);
6918
+ const key = crypto5.createPrivateKey(privateKeyPem);
6796
6919
  let signature;
6797
6920
  if (key.asymmetricKeyType === "rsa") {
6798
- signature = crypto4.sign("sha256", Buffer.from(dataToSign), {
6921
+ signature = crypto5.sign("sha256", Buffer.from(dataToSign), {
6799
6922
  key,
6800
- padding: crypto4.constants.RSA_PKCS1_PSS_PADDING,
6923
+ padding: crypto5.constants.RSA_PKCS1_PSS_PADDING,
6801
6924
  saltLength: 32
6802
6925
  });
6803
6926
  } else if (key.asymmetricKeyType === "ec") {
6804
- signature = crypto4.sign("sha256", Buffer.from(dataToSign), {
6927
+ signature = crypto5.sign("sha256", Buffer.from(dataToSign), {
6805
6928
  key,
6806
6929
  dsaEncoding: "ieee-p1363"
6807
6930
  });
@@ -6825,19 +6948,11 @@ __export(client_exports, {
6825
6948
  buildAuthTokenRequestXml: () => buildAuthTokenRequestXml
6826
6949
  });
6827
6950
  function buildAuthTokenRequestXml(challenge, nip, subjectIdentifierType = "certificateSubject") {
6828
- return [
6829
- '<?xml version="1.0" encoding="utf-8"?>',
6830
- `<AuthTokenRequest xmlns="${AUTH_TOKEN_REQUEST_NS}">`,
6831
- `<Challenge>${xmlEscape(challenge)}</Challenge>`,
6832
- `<ContextIdentifier>`,
6833
- `<Nip>${xmlEscape(nip)}</Nip>`,
6834
- `</ContextIdentifier>`,
6835
- `<SubjectIdentifierType>${xmlEscape(subjectIdentifierType)}</SubjectIdentifierType>`,
6836
- `</AuthTokenRequest>`
6837
- ].join("");
6838
- }
6839
- function xmlEscape(str) {
6840
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
6951
+ return buildUnsignedAuthTokenRequestXml({
6952
+ challenge,
6953
+ contextIdentifier: { type: "Nip", value: nip },
6954
+ subjectIdentifierType
6955
+ });
6841
6956
  }
6842
6957
  function buildRestClientConfig(options, authManager) {
6843
6958
  const config = { authManager };
@@ -6864,7 +6979,7 @@ function buildRestClientConfig(options, authManager) {
6864
6979
  }
6865
6980
  return config;
6866
6981
  }
6867
- var KSeFClient, AUTH_TOKEN_REQUEST_NS;
6982
+ var KSeFClient;
6868
6983
  var init_client = __esm({
6869
6984
  "src/client.ts"() {
6870
6985
  "use strict";
@@ -6890,6 +7005,7 @@ var init_client = __esm({
6890
7005
  init_certificate_fetcher();
6891
7006
  init_cryptography_service();
6892
7007
  init_verification_link_service();
7008
+ init_auth_xml_builder();
6893
7009
  KSeFClient = class {
6894
7010
  auth;
6895
7011
  activeSessions;
@@ -6933,7 +7049,7 @@ var init_client = __esm({
6933
7049
  this.lighthouse = new LighthouseService(this.options);
6934
7050
  this.limits = new LimitsService(restClient);
6935
7051
  this.peppol = new PeppolService(restClient);
6936
- this.testData = new TestDataService(restClient);
7052
+ this.testData = new TestDataService(restClient, this.options.environmentName);
6937
7053
  this.qr = new VerificationLinkService(this.options.baseQrUrl);
6938
7054
  }
6939
7055
  async loginWithToken(token, nip) {
@@ -6983,7 +7099,6 @@ var init_client = __esm({
6983
7099
  this.authManager.setRefreshToken(void 0);
6984
7100
  }
6985
7101
  };
6986
- AUTH_TOKEN_REQUEST_NS = "http://ksef.mf.gov.pl/auth/token/2.0";
6987
7102
  }
6988
7103
  });
6989
7104
 
@@ -7117,6 +7232,65 @@ var SUBUNIT_NAME_MAX_LENGTH = 256;
7117
7232
  var PERMISSION_DESCRIPTION_MIN_LENGTH = 5;
7118
7233
  var PERMISSION_DESCRIPTION_MAX_LENGTH = 256;
7119
7234
 
7235
+ // src/models/document-structures/types.ts
7236
+ var SystemCode = {
7237
+ FA_2: "FA (2)",
7238
+ FA_3: "FA (3)",
7239
+ PEF_3: "PEF (3)",
7240
+ PEF_KOR_3: "PEF_KOR (3)",
7241
+ FA_RR_1: "FA_RR (1)"
7242
+ };
7243
+ var FORM_CODES = {
7244
+ FA_2: { systemCode: "FA (2)", schemaVersion: "1-0E", value: "FA" },
7245
+ FA_3: { systemCode: "FA (3)", schemaVersion: "1-0E", value: "FA" },
7246
+ PEF_3: { systemCode: "PEF (3)", schemaVersion: "2-1", value: "PEF" },
7247
+ PEF_KOR_3: { systemCode: "PEF_KOR (3)", schemaVersion: "2-1", value: "PEF" },
7248
+ FA_RR_1_LEGACY: { systemCode: "FA_RR (1)", schemaVersion: "1-0E", value: "RR" },
7249
+ FA_RR_1_TRANSITION: { systemCode: "FA_RR (1)", schemaVersion: "1-1E", value: "RR" },
7250
+ FA_RR_1: { systemCode: "FA_RR (1)", schemaVersion: "1-1E", value: "FA_RR" }
7251
+ };
7252
+ var INVOICE_TYPES_BY_SYSTEM_CODE = {
7253
+ [SystemCode.FA_2]: ["Vat", "Zal", "Kor", "Roz", "Upr", "KorZal", "KorRoz"],
7254
+ [SystemCode.FA_3]: ["Vat", "Zal", "Kor", "Roz", "Upr", "KorZal", "KorRoz"],
7255
+ [SystemCode.PEF_3]: ["VatPef", "VatPefSp", "KorPef"],
7256
+ [SystemCode.PEF_KOR_3]: ["KorPef"],
7257
+ [SystemCode.FA_RR_1]: ["VatRr", "KorVatRr"]
7258
+ };
7259
+ var FORM_CODE_KEYS = {
7260
+ FA2: FORM_CODES.FA_2,
7261
+ FA3: FORM_CODES.FA_3,
7262
+ PEF3: FORM_CODES.PEF_3,
7263
+ PEFKOR3: FORM_CODES.PEF_KOR_3,
7264
+ FARR1: FORM_CODES.FA_RR_1
7265
+ };
7266
+
7267
+ // src/models/document-structures/helpers.ts
7268
+ var SYSTEM_CODE_TO_FORM_CODE = {
7269
+ [SystemCode.FA_2]: FORM_CODES.FA_2,
7270
+ [SystemCode.FA_3]: FORM_CODES.FA_3,
7271
+ [SystemCode.PEF_3]: FORM_CODES.PEF_3,
7272
+ [SystemCode.PEF_KOR_3]: FORM_CODES.PEF_KOR_3,
7273
+ [SystemCode.FA_RR_1]: FORM_CODES.FA_RR_1
7274
+ };
7275
+ var ALL_FORM_CODES = Object.values(FORM_CODES);
7276
+ var BATCH_DISALLOWED_SYSTEM_CODES = /* @__PURE__ */ new Set([
7277
+ SystemCode.PEF_3,
7278
+ SystemCode.PEF_KOR_3
7279
+ ]);
7280
+ function getFormCode(systemCode) {
7281
+ return SYSTEM_CODE_TO_FORM_CODE[systemCode];
7282
+ }
7283
+ function parseFormCode(raw) {
7284
+ const match = ALL_FORM_CODES.find(
7285
+ (fc) => fc.systemCode === raw.systemCode && fc.schemaVersion === raw.schemaVersion && fc.value === raw.value
7286
+ );
7287
+ return match ?? raw;
7288
+ }
7289
+ function validateFormCodeForSession(formCode, sessionType) {
7290
+ if (sessionType === "online") return true;
7291
+ return !BATCH_DISALLOWED_SYSTEM_CODES.has(formCode.systemCode);
7292
+ }
7293
+
7120
7294
  // src/services/index.ts
7121
7295
  init_auth();
7122
7296
  init_active_sessions();
@@ -7480,18 +7654,188 @@ var AuthorizationPermissionGrantBuilder = class {
7480
7654
  }
7481
7655
  };
7482
7656
 
7657
+ // src/builders/batch-file.ts
7658
+ init_ksef_validation_error();
7659
+ import * as crypto from "crypto";
7660
+ var BATCH_MAX_PART_SIZE = 1e8;
7661
+ var BATCH_MAX_TOTAL_SIZE = 5e9;
7662
+ var BATCH_MAX_PARTS = 50;
7663
+ var BatchFileBuilder = class {
7664
+ /**
7665
+ * Build batch file metadata and encrypted parts from a raw ZIP.
7666
+ *
7667
+ * @param zipBytes - Unencrypted ZIP data
7668
+ * @param encryptFn - AES-256-CBC encryption function (called per part)
7669
+ * @param options - Optional configuration
7670
+ */
7671
+ static build(zipBytes, encryptFn, options) {
7672
+ const maxPartSize = options?.maxPartSize ?? BATCH_MAX_PART_SIZE;
7673
+ if (maxPartSize <= 0) {
7674
+ throw new KSeFValidationError("maxPartSize must be a positive number");
7675
+ }
7676
+ if (zipBytes.length === 0) {
7677
+ throw new KSeFValidationError("ZIP data must not be empty");
7678
+ }
7679
+ if (zipBytes.length > BATCH_MAX_TOTAL_SIZE) {
7680
+ throw new KSeFValidationError(
7681
+ `ZIP size ${zipBytes.length} exceeds maximum of ${BATCH_MAX_TOTAL_SIZE} bytes (5 GB)`
7682
+ );
7683
+ }
7684
+ const rawParts = splitBuffer(zipBytes, maxPartSize);
7685
+ if (rawParts.length > BATCH_MAX_PARTS) {
7686
+ throw new KSeFValidationError(
7687
+ `Data requires ${rawParts.length} parts, exceeding maximum of ${BATCH_MAX_PARTS}`
7688
+ );
7689
+ }
7690
+ const zipHash = sha256Base64(zipBytes);
7691
+ const encryptedParts = [];
7692
+ const fileParts = rawParts.map((raw, i) => {
7693
+ const encrypted = encryptFn(raw);
7694
+ encryptedParts.push(encrypted);
7695
+ return {
7696
+ ordinalNumber: i + 1,
7697
+ fileSize: encrypted.length,
7698
+ fileHash: sha256Base64(encrypted)
7699
+ };
7700
+ });
7701
+ return {
7702
+ batchFile: {
7703
+ fileSize: zipBytes.length,
7704
+ fileHash: zipHash,
7705
+ fileParts
7706
+ },
7707
+ encryptedParts
7708
+ };
7709
+ }
7710
+ /**
7711
+ * Stream-based variant: two-pass build from a stream factory.
7712
+ *
7713
+ * Pass 1: consume stream to compute ZIP hash.
7714
+ * Pass 2: re-create stream, split into parts, encrypt each, compute per-part metadata.
7715
+ *
7716
+ * @param zipStreamFactory - Factory that creates a fresh ReadableStream of the ZIP data
7717
+ * @param zipSize - Total ZIP byte size (from fs.stat or known in advance)
7718
+ * @param encryptStreamFn - Stream-to-stream AES-256-CBC encryption function
7719
+ * @param hashStreamFn - Stream-to-FileMetadata hashing function
7720
+ * @param options - Optional configuration
7721
+ */
7722
+ static async buildFromStream(zipStreamFactory, zipSize, encryptStreamFn, hashStreamFn, options) {
7723
+ const maxPartSize = options?.maxPartSize ?? BATCH_MAX_PART_SIZE;
7724
+ if (maxPartSize <= 0) {
7725
+ throw new KSeFValidationError("maxPartSize must be a positive number");
7726
+ }
7727
+ if (zipSize === 0) {
7728
+ throw new KSeFValidationError("ZIP data must not be empty");
7729
+ }
7730
+ if (zipSize > BATCH_MAX_TOTAL_SIZE) {
7731
+ throw new KSeFValidationError(
7732
+ `ZIP size ${zipSize} exceeds maximum of ${BATCH_MAX_TOTAL_SIZE} bytes (5 GB)`
7733
+ );
7734
+ }
7735
+ const partCount = Math.ceil(zipSize / maxPartSize);
7736
+ if (partCount > BATCH_MAX_PARTS) {
7737
+ throw new KSeFValidationError(
7738
+ `Data requires ${partCount} parts, exceeding maximum of ${BATCH_MAX_PARTS}`
7739
+ );
7740
+ }
7741
+ const zipMeta = await hashStreamFn(zipStreamFactory());
7742
+ const fileParts = [];
7743
+ const streamParts = [];
7744
+ const reader = zipStreamFactory().getReader();
7745
+ let pending = [];
7746
+ let pendingSize = 0;
7747
+ for (let partIndex = 0; partIndex < partCount; partIndex++) {
7748
+ const isLastPart = partIndex === partCount - 1;
7749
+ const targetSize = isLastPart ? zipSize - partIndex * maxPartSize : maxPartSize;
7750
+ while (pendingSize < targetSize) {
7751
+ const { done, value } = await reader.read();
7752
+ if (done) break;
7753
+ pending.push(value);
7754
+ pendingSize += value.byteLength;
7755
+ }
7756
+ const buffer = new Uint8Array(Buffer.concat(pending));
7757
+ const partData = buffer.subarray(0, targetSize);
7758
+ if (buffer.byteLength > targetSize) {
7759
+ const remainder = buffer.subarray(targetSize);
7760
+ pending = [remainder];
7761
+ pendingSize = remainder.byteLength;
7762
+ } else {
7763
+ pending = [];
7764
+ pendingSize = 0;
7765
+ }
7766
+ const partStream = new ReadableStream({
7767
+ start(controller) {
7768
+ controller.enqueue(partData);
7769
+ controller.close();
7770
+ }
7771
+ });
7772
+ const encryptedStream = encryptStreamFn(partStream);
7773
+ const encryptedChunks = [];
7774
+ const encReader = encryptedStream.getReader();
7775
+ for (; ; ) {
7776
+ const { done, value } = await encReader.read();
7777
+ if (done) break;
7778
+ encryptedChunks.push(value);
7779
+ }
7780
+ const encryptedData = new Uint8Array(Buffer.concat(encryptedChunks));
7781
+ const encryptedMeta = sha256Base64(encryptedData);
7782
+ fileParts.push({
7783
+ ordinalNumber: partIndex + 1,
7784
+ fileSize: encryptedData.byteLength,
7785
+ fileHash: encryptedMeta
7786
+ });
7787
+ const uploadStream = new ReadableStream({
7788
+ start(controller) {
7789
+ controller.enqueue(encryptedData);
7790
+ controller.close();
7791
+ }
7792
+ });
7793
+ streamParts.push({
7794
+ dataStream: uploadStream,
7795
+ metadata: {
7796
+ hashSHA: encryptedMeta,
7797
+ fileSize: encryptedData.byteLength
7798
+ },
7799
+ ordinalNumber: partIndex + 1
7800
+ });
7801
+ }
7802
+ reader.releaseLock();
7803
+ return {
7804
+ batchFile: {
7805
+ fileSize: zipSize,
7806
+ fileHash: zipMeta.hashSHA,
7807
+ fileParts
7808
+ },
7809
+ streamParts
7810
+ };
7811
+ }
7812
+ };
7813
+ function splitBuffer(data, maxPartSize) {
7814
+ if (data.length <= maxPartSize) {
7815
+ return [data];
7816
+ }
7817
+ const parts = [];
7818
+ for (let offset = 0; offset < data.length; offset += maxPartSize) {
7819
+ parts.push(data.subarray(offset, Math.min(offset + maxPartSize, data.length)));
7820
+ }
7821
+ return parts;
7822
+ }
7823
+ function sha256Base64(data) {
7824
+ return crypto.createHash("sha256").update(data).digest("base64");
7825
+ }
7826
+
7483
7827
  // src/crypto/index.ts
7484
7828
  init_certificate_fetcher();
7485
7829
  init_cryptography_service();
7486
7830
  init_signature_service();
7487
7831
 
7488
7832
  // src/crypto/certificate-service.ts
7489
- import * as crypto3 from "crypto";
7833
+ import * as crypto4 from "crypto";
7490
7834
  import * as x5092 from "@peculiar/x509";
7491
7835
  var CertificateService = class {
7492
7836
  static getSha256Fingerprint(certPem) {
7493
7837
  const der = extractDerFromPem2(certPem);
7494
- return crypto3.createHash("sha256").update(der).digest("hex").toUpperCase();
7838
+ return crypto4.createHash("sha256").update(der).digest("hex").toUpperCase();
7495
7839
  }
7496
7840
  static async generatePersonalCertificate(givenName, surname, serialNumber, commonName, method = "RSA") {
7497
7841
  const nameParts = [];
@@ -7514,7 +7858,7 @@ var CertificateService = class {
7514
7858
  }
7515
7859
  };
7516
7860
  async function generateSelfSigned(subject, method) {
7517
- x5092.cryptoProvider.set(crypto3.webcrypto);
7861
+ x5092.cryptoProvider.set(crypto4.webcrypto);
7518
7862
  let algorithm;
7519
7863
  let signingAlgorithm;
7520
7864
  if (method === "ECDSA") {
@@ -7529,7 +7873,7 @@ async function generateSelfSigned(subject, method) {
7529
7873
  };
7530
7874
  signingAlgorithm = algorithm;
7531
7875
  }
7532
- const keys = await crypto3.webcrypto.subtle.generateKey(
7876
+ const keys = await crypto4.webcrypto.subtle.generateKey(
7533
7877
  algorithm,
7534
7878
  true,
7535
7879
  ["sign", "verify"]
@@ -7546,9 +7890,9 @@ async function generateSelfSigned(subject, method) {
7546
7890
  serialNumber: Date.now().toString(16)
7547
7891
  });
7548
7892
  const certPem = cert.toString("pem");
7549
- const pkcs8 = await crypto3.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7893
+ const pkcs8 = await crypto4.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7550
7894
  const privateKeyPem = pemEncode2(new Uint8Array(pkcs8), "PRIVATE KEY");
7551
- const fingerprint = crypto3.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
7895
+ const fingerprint = crypto4.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
7552
7896
  return { certificatePem: certPem, privateKeyPem, fingerprint };
7553
7897
  }
7554
7898
  function extractDerFromPem2(pem) {
@@ -7568,6 +7912,7 @@ ${lines.join("\n")}
7568
7912
 
7569
7913
  // src/crypto/index.ts
7570
7914
  init_pkcs12_loader();
7915
+ init_auth_xml_builder();
7571
7916
 
7572
7917
  // src/qr/index.ts
7573
7918
  init_verification_link_service();
@@ -7631,6 +7976,94 @@ function escapeXml2(str) {
7631
7976
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
7632
7977
  }
7633
7978
 
7979
+ // src/utils/zip.ts
7980
+ import { ZipFile } from "yazl";
7981
+ import { fromBuffer } from "yauzl";
7982
+ var DEFAULT_UNZIP_OPTIONS = {
7983
+ maxFiles: 1e4,
7984
+ maxTotalUncompressedSize: 2e9,
7985
+ maxFileUncompressedSize: 5e8,
7986
+ maxCompressionRatio: 200
7987
+ };
7988
+ async function createZip(entries) {
7989
+ return new Promise((resolve, reject) => {
7990
+ const zipfile = new ZipFile();
7991
+ for (const entry of entries) {
7992
+ zipfile.addBuffer(Buffer.from(entry.content), entry.fileName);
7993
+ }
7994
+ const chunks = [];
7995
+ zipfile.outputStream.on("data", (chunk) => chunks.push(chunk));
7996
+ zipfile.outputStream.on("error", (err) => reject(err));
7997
+ zipfile.outputStream.on("end", () => resolve(Buffer.concat(chunks)));
7998
+ zipfile.end();
7999
+ });
8000
+ }
8001
+ async function unzip(buffer, options = {}) {
8002
+ const limits = { ...DEFAULT_UNZIP_OPTIONS, ...options };
8003
+ return new Promise((resolve, reject) => {
8004
+ fromBuffer(buffer, { lazyEntries: true }, (err, zipfile) => {
8005
+ if (err || !zipfile) {
8006
+ reject(err ?? new Error("Failed to open zip buffer"));
8007
+ return;
8008
+ }
8009
+ const files = /* @__PURE__ */ new Map();
8010
+ let totalUncompressed = 0;
8011
+ zipfile.readEntry();
8012
+ zipfile.on("entry", (entry) => {
8013
+ if (entry.fileName.endsWith("/")) {
8014
+ zipfile.readEntry();
8015
+ return;
8016
+ }
8017
+ if (limits.maxFiles > 0 && files.size >= limits.maxFiles) {
8018
+ reject(new Error("zip contains too many files"));
8019
+ return;
8020
+ }
8021
+ const uncompressedSize = entry.uncompressedSize ?? 0;
8022
+ const compressedSize = entry.compressedSize ?? 0;
8023
+ if (limits.maxFileUncompressedSize > 0 && uncompressedSize > limits.maxFileUncompressedSize) {
8024
+ reject(new Error("zip entry exceeds max_file_uncompressed_size"));
8025
+ return;
8026
+ }
8027
+ if (limits.maxTotalUncompressedSize > 0) {
8028
+ totalUncompressed += uncompressedSize;
8029
+ if (totalUncompressed > limits.maxTotalUncompressedSize) {
8030
+ reject(new Error("zip exceeds max_total_uncompressed_size"));
8031
+ return;
8032
+ }
8033
+ }
8034
+ if (limits.maxCompressionRatio !== null) {
8035
+ if (compressedSize === 0 && uncompressedSize > 0) {
8036
+ reject(new Error("zip entry has suspicious compression metadata"));
8037
+ return;
8038
+ }
8039
+ if (compressedSize > 0 && uncompressedSize > 0) {
8040
+ const ratio = uncompressedSize / compressedSize;
8041
+ if (ratio > limits.maxCompressionRatio) {
8042
+ reject(new Error("zip entry exceeds max_compression_ratio"));
8043
+ return;
8044
+ }
8045
+ }
8046
+ }
8047
+ zipfile.openReadStream(entry, (streamErr, stream) => {
8048
+ if (streamErr || !stream) {
8049
+ reject(streamErr ?? new Error("Failed to read zip entry"));
8050
+ return;
8051
+ }
8052
+ const chunks = [];
8053
+ stream.on("data", (chunk) => chunks.push(chunk));
8054
+ stream.on("error", (streamError) => reject(streamError));
8055
+ stream.on("end", () => {
8056
+ files.set(entry.fileName, Buffer.concat(chunks));
8057
+ zipfile.readEntry();
8058
+ });
8059
+ });
8060
+ });
8061
+ zipfile.on("end", () => resolve(files));
8062
+ zipfile.on("error", (zipErr) => reject(zipErr));
8063
+ });
8064
+ });
8065
+ }
8066
+
7634
8067
  // src/workflows/polling.ts
7635
8068
  async function pollUntil(action, condition, options) {
7636
8069
  const intervalMs = options?.intervalMs ?? 2e3;
@@ -7648,17 +8081,150 @@ async function pollUntil(action, condition, options) {
7648
8081
  );
7649
8082
  }
7650
8083
 
8084
+ // src/xml/upo-parser.ts
8085
+ init_ksef_validation_error();
8086
+ import { XMLParser } from "fast-xml-parser";
8087
+ function isRecord(value) {
8088
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8089
+ }
8090
+ function requireRecord(value, at) {
8091
+ if (!isRecord(value)) {
8092
+ throw KSeFValidationError.fromField(at, `Expected object at ${at}`);
8093
+ }
8094
+ return value;
8095
+ }
8096
+ function requireString(value, at) {
8097
+ if (typeof value !== "string" || value.length === 0) {
8098
+ throw KSeFValidationError.fromField(at, `Expected non-empty string at ${at}`);
8099
+ }
8100
+ return value;
8101
+ }
8102
+ function optionalRecord(value) {
8103
+ return isRecord(value) ? value : void 0;
8104
+ }
8105
+ function optionalString(value) {
8106
+ return typeof value === "string" && value.length > 0 ? value : void 0;
8107
+ }
8108
+ function requireNumberFromString(value, at) {
8109
+ const raw = requireString(value, at);
8110
+ const parsed = Number.parseInt(raw, 10);
8111
+ if (!Number.isFinite(parsed)) {
8112
+ throw KSeFValidationError.fromField(at, `Expected integer at ${at}, got "${raw}"`);
8113
+ }
8114
+ return parsed;
8115
+ }
8116
+ function ensureArray(value) {
8117
+ if (value == null) return [];
8118
+ return Array.isArray(value) ? value : [value];
8119
+ }
8120
+ function parseIdKontekstu(obj) {
8121
+ const nip = optionalString(obj.Nip);
8122
+ if (nip) return { kind: "Nip", nip };
8123
+ const idWewnetrzny = optionalString(obj.IdWewnetrzny);
8124
+ if (idWewnetrzny) return { kind: "IdWewnetrzny", idWewnetrzny };
8125
+ const idZlozonyVatUE = optionalString(obj.IdZlozonyVatUE);
8126
+ if (idZlozonyVatUE) return { kind: "IdZlozonyVatUE", idZlozonyVatUE };
8127
+ const idDostawcyUslugPeppol = optionalString(obj.IdDostawcyUslugPeppol);
8128
+ if (idDostawcyUslugPeppol) return { kind: "IdDostawcyUslugPeppol", idDostawcyUslugPeppol };
8129
+ throw KSeFValidationError.fromField(
8130
+ "Uwierzytelnienie.IdKontekstu",
8131
+ "Unsupported context identifier. Expected Nip | IdWewnetrzny | IdZlozonyVatUE | IdDostawcyUslugPeppol"
8132
+ );
8133
+ }
8134
+ function parseProof(obj) {
8135
+ const tokenRef = optionalString(obj.NumerReferencyjnyTokenaKSeF);
8136
+ if (tokenRef) return { kind: "NumerReferencyjnyTokenaKSeF", numerReferencyjnyTokenaKSeF: tokenRef };
8137
+ const docHash = optionalString(obj.SkrotDokumentuUwierzytelniajacego);
8138
+ if (docHash) return { kind: "SkrotDokumentuUwierzytelniajacego", skrotDokumentuUwierzytelniajacego: docHash };
8139
+ throw KSeFValidationError.fromField(
8140
+ "Uwierzytelnienie",
8141
+ "Unsupported auth proof. Expected NumerReferencyjnyTokenaKSeF | SkrotDokumentuUwierzytelniajacego"
8142
+ );
8143
+ }
8144
+ function parseUwierzytelnienie(obj) {
8145
+ const idKontekstu = parseIdKontekstu(
8146
+ requireRecord(obj.IdKontekstu, "Uwierzytelnienie.IdKontekstu")
8147
+ );
8148
+ const proof = parseProof(obj);
8149
+ return { idKontekstu, proof };
8150
+ }
8151
+ function parseOpisPotwierdzenia(obj) {
8152
+ return {
8153
+ strona: requireNumberFromString(obj.Strona, "OpisPotwierdzenia.Strona"),
8154
+ liczbaStron: requireNumberFromString(obj.LiczbaStron, "OpisPotwierdzenia.LiczbaStron"),
8155
+ zakresDokumentowOd: requireNumberFromString(obj.ZakresDokumentowOd, "OpisPotwierdzenia.ZakresDokumentowOd"),
8156
+ zakresDokumentowDo: requireNumberFromString(obj.ZakresDokumentowDo, "OpisPotwierdzenia.ZakresDokumentowDo"),
8157
+ calkowitaLiczbaDokumentow: requireNumberFromString(obj.CalkowitaLiczbaDokumentow, "OpisPotwierdzenia.CalkowitaLiczbaDokumentow")
8158
+ };
8159
+ }
8160
+ function parseDokument(obj) {
8161
+ return {
8162
+ nipSprzedawcy: requireString(obj.NipSprzedawcy, "Dokument.NipSprzedawcy"),
8163
+ numerKSeFDokumentu: requireString(obj.NumerKSeFDokumentu, "Dokument.NumerKSeFDokumentu"),
8164
+ numerFaktury: requireString(obj.NumerFaktury, "Dokument.NumerFaktury"),
8165
+ dataWystawieniaFaktury: requireString(obj.DataWystawieniaFaktury, "Dokument.DataWystawieniaFaktury"),
8166
+ dataPrzeslaniaDokumentu: requireString(obj.DataPrzeslaniaDokumentu, "Dokument.DataPrzeslaniaDokumentu"),
8167
+ dataNadaniaNumeruKSeF: requireString(obj.DataNadaniaNumeruKSeF, "Dokument.DataNadaniaNumeruKSeF"),
8168
+ skrotDokumentu: requireString(obj.SkrotDokumentu, "Dokument.SkrotDokumentu"),
8169
+ trybWysylki: requireString(obj.TrybWysylki, "Dokument.TrybWysylki")
8170
+ };
8171
+ }
8172
+ var upoParser = new XMLParser({
8173
+ ignoreAttributes: false,
8174
+ attributeNamePrefix: "@_",
8175
+ parseTagValue: false,
8176
+ parseAttributeValue: false,
8177
+ removeNSPrefix: true,
8178
+ trimValues: false
8179
+ });
8180
+ function parseUpoXml(xml) {
8181
+ const text = Buffer.isBuffer(xml) ? xml.toString("utf8") : xml;
8182
+ const parsed = upoParser.parse(text);
8183
+ const potwierdzenie = requireRecord(parsed?.Potwierdzenie, "Potwierdzenie");
8184
+ const opisPotwierdzenia = optionalRecord(potwierdzenie.OpisPotwierdzenia);
8185
+ const dokumenty = ensureArray(potwierdzenie.Dokument).map(
8186
+ (doc, i) => parseDokument(requireRecord(doc, `Dokument[${i}]`))
8187
+ );
8188
+ if (dokumenty.length === 0) {
8189
+ throw KSeFValidationError.fromField("Dokument", "Expected at least one Dokument in UPO");
8190
+ }
8191
+ return {
8192
+ nazwaPodmiotuPrzyjmujacego: requireString(potwierdzenie.NazwaPodmiotuPrzyjmujacego, "NazwaPodmiotuPrzyjmujacego"),
8193
+ numerReferencyjnySesji: requireString(potwierdzenie.NumerReferencyjnySesji, "NumerReferencyjnySesji"),
8194
+ uwierzytelnienie: parseUwierzytelnienie(requireRecord(potwierdzenie.Uwierzytelnienie, "Uwierzytelnienie")),
8195
+ ...opisPotwierdzenia && { opisPotwierdzenia: parseOpisPotwierdzenia(opisPotwierdzenia) },
8196
+ nazwaStrukturyLogicznej: requireString(potwierdzenie.NazwaStrukturyLogicznej, "NazwaStrukturyLogicznej"),
8197
+ kodFormularza: requireString(potwierdzenie.KodFormularza, "KodFormularza"),
8198
+ dokumenty
8199
+ };
8200
+ }
8201
+
7651
8202
  // src/workflows/online-session-workflow.ts
7652
- var DEFAULT_FORM_CODE = { systemCode: "FA", schemaVersion: "3", value: "FA (3)" };
7653
8203
  async function openOnlineSession(client, options) {
7654
8204
  await client.crypto.init();
7655
8205
  const encData = client.crypto.getEncryptionData();
7656
- const formCode = options?.formCode ?? DEFAULT_FORM_CODE;
8206
+ const formCode = options?.formCode ?? FORM_CODES.FA_2;
7657
8207
  const openResp = await client.onlineSession.openSession(
7658
8208
  { formCode, encryption: encData.encryptionInfo },
7659
8209
  options?.upoVersion
7660
8210
  );
7661
8211
  const sessionRef = openResp.referenceNumber;
8212
+ async function fetchUpo(pollOpts) {
8213
+ const result = await pollUntil(
8214
+ () => client.sessionStatus.getSessionStatus(sessionRef),
8215
+ (s) => s.status.code === 200 || s.status.code >= 400,
8216
+ { ...pollOpts, description: `UPO for session ${sessionRef}` }
8217
+ );
8218
+ if (result.status.code !== 200) {
8219
+ throw new Error(`Session failed: ${result.status.code} \u2014 ${result.status.description}`);
8220
+ }
8221
+ return {
8222
+ pages: result.upo?.pages ?? [],
8223
+ invoiceCount: result.invoiceCount,
8224
+ successfulInvoiceCount: result.successfulInvoiceCount,
8225
+ failedInvoiceCount: result.failedInvoiceCount
8226
+ };
8227
+ }
7662
8228
  return {
7663
8229
  sessionRef,
7664
8230
  validUntil: openResp.validUntil,
@@ -7680,20 +8246,16 @@ async function openOnlineSession(client, options) {
7680
8246
  await client.onlineSession.closeSession(sessionRef);
7681
8247
  },
7682
8248
  async waitForUpo(pollOpts) {
7683
- const result = await pollUntil(
7684
- () => client.sessionStatus.getSessionStatus(sessionRef),
7685
- (s) => s.status.code !== 100,
7686
- { ...pollOpts, description: `UPO for session ${sessionRef}` }
7687
- );
7688
- if (result.status.code !== 200) {
7689
- throw new Error(`Session failed: ${result.status.code} \u2014 ${result.status.description}`);
7690
- }
7691
- return {
7692
- pages: result.upo?.pages ?? [],
7693
- invoiceCount: result.invoiceCount,
7694
- successfulInvoiceCount: result.successfulInvoiceCount,
7695
- failedInvoiceCount: result.failedInvoiceCount
7696
- };
8249
+ return fetchUpo(pollOpts);
8250
+ },
8251
+ async waitForUpoParsed(pollOpts) {
8252
+ const upoInfo = await fetchUpo(pollOpts);
8253
+ const parsed = [];
8254
+ for (const page of upoInfo.pages) {
8255
+ const result = await client.sessionStatus.getSessionUpo(sessionRef, page.referenceNumber);
8256
+ parsed.push(parseUpoXml(result.upo));
8257
+ }
8258
+ return { ...upoInfo, parsed };
7697
8259
  }
7698
8260
  };
7699
8261
  }
@@ -7707,32 +8269,36 @@ async function openSendAndClose(client, invoices, options) {
7707
8269
  }
7708
8270
 
7709
8271
  // src/workflows/batch-session-workflow.ts
7710
- var DEFAULT_FORM_CODE2 = { systemCode: "FA", schemaVersion: "3", value: "FA (3)" };
7711
- async function uploadBatch(client, zipParts, totalFileSize, totalFileHash, options) {
8272
+ async function uploadBatch(client, zipData, options) {
7712
8273
  await client.crypto.init();
7713
8274
  const encData = client.crypto.getEncryptionData();
7714
- 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 };
8275
+ const formCode = options?.formCode ?? FORM_CODES.FA_2;
8276
+ const encryptFn = (part) => client.crypto.encryptAES256(part, encData.cipherKey, encData.cipherIv);
8277
+ const { batchFile, encryptedParts } = BatchFileBuilder.build(zipData, encryptFn, {
8278
+ maxPartSize: options?.maxPartSize
7718
8279
  });
7719
8280
  const openResp = await client.batchSession.openSession(
7720
8281
  {
7721
8282
  formCode,
7722
8283
  encryption: encData.encryptionInfo,
7723
- batchFile: { fileSize: totalFileSize, fileHash: totalFileHash, fileParts }
8284
+ batchFile,
8285
+ offlineMode: options?.offlineMode
7724
8286
  },
7725
8287
  options?.upoVersion
7726
8288
  );
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
- });
8289
+ const sendingParts = encryptedParts.map((part, i) => ({
8290
+ data: part.buffer.slice(part.byteOffset, part.byteOffset + part.byteLength),
8291
+ metadata: {
8292
+ hashSHA: batchFile.fileParts[i].fileHash,
8293
+ fileSize: batchFile.fileParts[i].fileSize
8294
+ },
8295
+ ordinalNumber: i + 1
8296
+ }));
7731
8297
  await client.batchSession.sendParts(openResp, sendingParts);
7732
8298
  await client.batchSession.closeSession(openResp.referenceNumber);
7733
8299
  const result = await pollUntil(
7734
8300
  () => client.sessionStatus.getSessionStatus(openResp.referenceNumber),
7735
- (s) => s.status.code !== 100,
8301
+ (s) => s.status.code === 200 || s.status.code >= 400,
7736
8302
  { ...options?.pollOptions, description: `UPO for batch ${openResp.referenceNumber}` }
7737
8303
  );
7738
8304
  if (result.status.code !== 200) {
@@ -7748,9 +8314,75 @@ async function uploadBatch(client, zipParts, totalFileSize, totalFileHash, optio
7748
8314
  }
7749
8315
  };
7750
8316
  }
8317
+ async function uploadBatchStream(client, zipStreamFactory, zipSize, options) {
8318
+ await client.crypto.init();
8319
+ const encData = client.crypto.getEncryptionData();
8320
+ const formCode = options?.formCode ?? FORM_CODES.FA_2;
8321
+ const encryptStreamFn = (stream) => client.crypto.encryptAES256Stream(stream, encData.cipherKey, encData.cipherIv);
8322
+ const hashStreamFn = (stream) => client.crypto.getFileMetadataFromStream(stream);
8323
+ const { batchFile, streamParts } = await BatchFileBuilder.buildFromStream(
8324
+ zipStreamFactory,
8325
+ zipSize,
8326
+ encryptStreamFn,
8327
+ hashStreamFn,
8328
+ { maxPartSize: options?.maxPartSize }
8329
+ );
8330
+ const openResp = await client.batchSession.openSession(
8331
+ {
8332
+ formCode,
8333
+ encryption: encData.encryptionInfo,
8334
+ batchFile,
8335
+ offlineMode: options?.offlineMode
8336
+ },
8337
+ options?.upoVersion
8338
+ );
8339
+ await client.batchSession.sendPartsWithStream(openResp, streamParts);
8340
+ await client.batchSession.closeSession(openResp.referenceNumber);
8341
+ const result = await pollUntil(
8342
+ () => client.sessionStatus.getSessionStatus(openResp.referenceNumber),
8343
+ (s) => s.status.code === 200 || s.status.code >= 400,
8344
+ { ...options?.pollOptions, description: `UPO for batch ${openResp.referenceNumber}` }
8345
+ );
8346
+ if (result.status.code !== 200) {
8347
+ throw new Error(`Batch session failed: ${result.status.code} \u2014 ${result.status.description}`);
8348
+ }
8349
+ return {
8350
+ sessionRef: openResp.referenceNumber,
8351
+ upo: {
8352
+ pages: result.upo?.pages ?? [],
8353
+ invoiceCount: result.invoiceCount,
8354
+ successfulInvoiceCount: result.successfulInvoiceCount,
8355
+ failedInvoiceCount: result.failedInvoiceCount
8356
+ }
8357
+ };
8358
+ }
8359
+ async function uploadBatchStreamParsed(client, zipStreamFactory, zipSize, options) {
8360
+ const result = await uploadBatchStream(client, zipStreamFactory, zipSize, options);
8361
+ const parsed = [];
8362
+ for (const page of result.upo.pages) {
8363
+ const upoResult = await client.sessionStatus.getSessionUpo(result.sessionRef, page.referenceNumber);
8364
+ parsed.push(parseUpoXml(upoResult.upo));
8365
+ }
8366
+ return {
8367
+ sessionRef: result.sessionRef,
8368
+ upo: { ...result.upo, parsed }
8369
+ };
8370
+ }
8371
+ async function uploadBatchParsed(client, zipData, options) {
8372
+ const result = await uploadBatch(client, zipData, options);
8373
+ const parsed = [];
8374
+ for (const page of result.upo.pages) {
8375
+ const upoResult = await client.sessionStatus.getSessionUpo(result.sessionRef, page.referenceNumber);
8376
+ parsed.push(parseUpoXml(upoResult.upo));
8377
+ }
8378
+ return {
8379
+ sessionRef: result.sessionRef,
8380
+ upo: { ...result.upo, parsed }
8381
+ };
8382
+ }
7751
8383
 
7752
8384
  // src/workflows/invoice-export-workflow.ts
7753
- async function exportInvoices(client, filters, options) {
8385
+ async function doExport(client, filters, options) {
7754
8386
  await client.crypto.init();
7755
8387
  const encData = client.crypto.getEncryptionData();
7756
8388
  const opResp = await client.invoices.exportInvoices({
@@ -7760,7 +8392,7 @@ async function exportInvoices(client, filters, options) {
7760
8392
  });
7761
8393
  const result = await pollUntil(
7762
8394
  () => client.invoices.getInvoiceExportStatus(opResp.referenceNumber),
7763
- (s) => s.status.code !== 100,
8395
+ (s) => s.status.code === 200 || s.status.code >= 400,
7764
8396
  { ...options?.pollOptions, description: `export ${opResp.referenceNumber}` }
7765
8397
  );
7766
8398
  if (result.status.code !== 200) {
@@ -7770,23 +8402,31 @@ async function exportInvoices(client, filters, options) {
7770
8402
  throw new Error("Export completed but no package available");
7771
8403
  }
7772
8404
  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
8405
+ encData,
8406
+ referenceNumber: opResp.referenceNumber,
8407
+ result: {
8408
+ parts: result.package.parts.map((p) => ({
8409
+ ordinalNumber: p.ordinalNumber,
8410
+ url: p.url,
8411
+ method: p.method,
8412
+ partSize: p.partSize,
8413
+ encryptedPartSize: p.encryptedPartSize,
8414
+ encryptedPartHash: p.encryptedPartHash,
8415
+ expirationDate: p.expirationDate
8416
+ })),
8417
+ invoiceCount: result.package.invoiceCount,
8418
+ isTruncated: result.package.isTruncated,
8419
+ permanentStorageHwmDate: result.package.permanentStorageHwmDate,
8420
+ lastPermanentStorageDate: result.package.lastPermanentStorageDate
8421
+ }
7785
8422
  };
7786
8423
  }
8424
+ async function exportInvoices(client, filters, options) {
8425
+ const { result } = await doExport(client, filters, options);
8426
+ return result;
8427
+ }
7787
8428
  async function exportAndDownload(client, filters, options) {
7788
- const encData = client.crypto.getEncryptionData();
7789
- const exportResult = await exportInvoices(client, filters, options);
8429
+ const { result: exportResult, encData } = await doExport(client, filters, options);
7790
8430
  const download = options?.transport ?? fetch;
7791
8431
  const decryptedParts = [];
7792
8432
  for (const part of exportResult.parts) {
@@ -7798,13 +8438,144 @@ async function exportAndDownload(client, filters, options) {
7798
8438
  const decrypted = client.crypto.decryptAES256(encryptedData, encData.cipherKey, encData.cipherIv);
7799
8439
  decryptedParts.push(decrypted);
7800
8440
  }
8441
+ if (options?.extract) {
8442
+ const zipBuffer = Buffer.concat(decryptedParts);
8443
+ const files = await unzip(zipBuffer, options.unzipOptions);
8444
+ return { ...exportResult, files };
8445
+ }
7801
8446
  return {
7802
8447
  ...exportResult,
7803
8448
  decryptedParts
7804
8449
  };
7805
8450
  }
7806
8451
 
8452
+ // src/workflows/hwm-coordinator.ts
8453
+ function updateContinuationPoint(points, subjectType, pkg) {
8454
+ if (pkg.isTruncated && pkg.lastPermanentStorageDate) {
8455
+ points[subjectType] = pkg.lastPermanentStorageDate;
8456
+ } else if (pkg.permanentStorageHwmDate) {
8457
+ points[subjectType] = pkg.permanentStorageHwmDate;
8458
+ } else {
8459
+ delete points[subjectType];
8460
+ }
8461
+ }
8462
+ function getEffectiveStartDate(points, subjectType, windowFrom) {
8463
+ return points[subjectType] ?? windowFrom;
8464
+ }
8465
+ function deduplicateByKsefNumber(entries) {
8466
+ const seen = /* @__PURE__ */ new Set();
8467
+ return entries.filter((entry) => {
8468
+ const key = entry.ksefNumber.toLowerCase();
8469
+ if (seen.has(key)) return false;
8470
+ seen.add(key);
8471
+ return true;
8472
+ });
8473
+ }
8474
+
8475
+ // src/workflows/incremental-export-workflow.ts
8476
+ async function incrementalExportAndDownload(client, options) {
8477
+ const maxIterations = options.maxIterations ?? 20;
8478
+ const points = options.continuationPoints;
8479
+ if (options.store) {
8480
+ const loaded = await options.store.load();
8481
+ for (const [key, value] of Object.entries(loaded)) {
8482
+ if (value !== void 0 && points[key] === void 0) {
8483
+ points[key] = value;
8484
+ }
8485
+ }
8486
+ }
8487
+ const referenceNumbers = [];
8488
+ const decryptedParts = [];
8489
+ let previousFrom;
8490
+ let iteration = 0;
8491
+ for (; iteration < maxIterations; iteration++) {
8492
+ const effectiveFrom = getEffectiveStartDate(points, options.subjectType, options.windowFrom);
8493
+ if (previousFrom !== void 0 && effectiveFrom === previousFrom) {
8494
+ break;
8495
+ }
8496
+ previousFrom = effectiveFrom;
8497
+ const filters = options.filtersFactory ? options.filtersFactory(effectiveFrom, options.windowTo) : buildDefaultFilters(options.subjectType, effectiveFrom, options.windowTo);
8498
+ const { result, encData, referenceNumber } = await doExport(client, filters, {
8499
+ onlyMetadata: options.onlyMetadata,
8500
+ pollOptions: options.pollOptions
8501
+ });
8502
+ referenceNumbers.push(referenceNumber);
8503
+ const download = options.transport ?? fetch;
8504
+ for (const part of result.parts) {
8505
+ const resp = await download(part.url, { method: part.method });
8506
+ if (!resp.ok) {
8507
+ throw new Error(`Download failed for part ${part.ordinalNumber}: HTTP ${resp.status}`);
8508
+ }
8509
+ const encryptedData = new Uint8Array(await resp.arrayBuffer());
8510
+ const decrypted = client.crypto.decryptAES256(encryptedData, encData.cipherKey, encData.cipherIv);
8511
+ decryptedParts.push(decrypted);
8512
+ }
8513
+ updateContinuationPoint(points, options.subjectType, {
8514
+ isTruncated: result.isTruncated,
8515
+ lastPermanentStorageDate: result.lastPermanentStorageDate,
8516
+ permanentStorageHwmDate: result.permanentStorageHwmDate
8517
+ });
8518
+ if (options.store) {
8519
+ await options.store.save(points);
8520
+ }
8521
+ options.onIterationComplete?.(iteration, result);
8522
+ if (!result.isTruncated) {
8523
+ iteration++;
8524
+ break;
8525
+ }
8526
+ }
8527
+ return {
8528
+ referenceNumbers,
8529
+ invoices: [],
8530
+ decryptedParts,
8531
+ continuationPoints: points,
8532
+ iterationCount: iteration
8533
+ };
8534
+ }
8535
+ function buildDefaultFilters(subjectType, from, to) {
8536
+ return {
8537
+ subjectType,
8538
+ dateRange: {
8539
+ dateType: "PermanentStorage",
8540
+ from,
8541
+ to
8542
+ }
8543
+ };
8544
+ }
8545
+
8546
+ // src/workflows/hwm-storage.ts
8547
+ import * as fs from "fs/promises";
8548
+ var InMemoryHwmStore = class {
8549
+ points = {};
8550
+ async load() {
8551
+ return { ...this.points };
8552
+ }
8553
+ async save(points) {
8554
+ this.points = { ...points };
8555
+ }
8556
+ };
8557
+ var FileHwmStore = class {
8558
+ constructor(filePath) {
8559
+ this.filePath = filePath;
8560
+ }
8561
+ async load() {
8562
+ try {
8563
+ const data = await fs.readFile(this.filePath, "utf-8");
8564
+ return JSON.parse(data);
8565
+ } catch (err) {
8566
+ if (err.code === "ENOENT") {
8567
+ return {};
8568
+ }
8569
+ throw err;
8570
+ }
8571
+ }
8572
+ async save(points) {
8573
+ await fs.writeFile(this.filePath, JSON.stringify(points, null, 2), "utf-8");
8574
+ }
8575
+ };
8576
+
7807
8577
  // src/workflows/auth-workflow.ts
8578
+ init_auth_xml_builder();
7808
8579
  async function authenticateWithToken(client, options) {
7809
8580
  const challenge = await client.auth.getChallenge();
7810
8581
  await client.crypto.init();
@@ -7858,6 +8629,34 @@ async function authenticateWithCertificate(client, options) {
7858
8629
  refreshTokenValidUntil: tokens.refreshToken.validUntil
7859
8630
  };
7860
8631
  }
8632
+ async function authenticateWithExternalSignature(client, options) {
8633
+ const challenge = await client.auth.getChallenge();
8634
+ const unsignedXml = buildUnsignedAuthTokenRequestXml({
8635
+ challenge: challenge.challenge,
8636
+ contextIdentifier: options.contextIdentifier
8637
+ });
8638
+ const signedXml = await options.signXml(unsignedXml);
8639
+ const submitResult = await client.auth.submitXadesAuthRequest(
8640
+ signedXml,
8641
+ options.verifyCertificateChain ?? false,
8642
+ options.enforceXadesCompliance ?? false
8643
+ );
8644
+ const authToken = submitResult.authenticationToken.token;
8645
+ await pollUntil(
8646
+ () => client.auth.getAuthStatus(submitResult.referenceNumber, authToken),
8647
+ (s) => s.status.code !== 100,
8648
+ { ...options.pollOptions, description: `auth ${submitResult.referenceNumber}` }
8649
+ );
8650
+ const tokens = await client.auth.getAccessToken(authToken);
8651
+ client.authManager.setAccessToken(tokens.accessToken.token);
8652
+ client.authManager.setRefreshToken(tokens.refreshToken.token);
8653
+ return {
8654
+ accessToken: tokens.accessToken.token,
8655
+ accessTokenValidUntil: tokens.accessToken.validUntil,
8656
+ refreshToken: tokens.refreshToken.token,
8657
+ refreshTokenValidUntil: tokens.refreshToken.validUntil
8658
+ };
8659
+ }
7861
8660
  async function authenticateWithPkcs12(client, options) {
7862
8661
  const { Pkcs12Loader: Pkcs12Loader2 } = await Promise.resolve().then(() => (init_pkcs12_loader(), pkcs12_loader_exports));
7863
8662
  const { certificatePem, privateKeyPem } = Pkcs12Loader2.load(options.p12, options.password);
@@ -7879,7 +8678,11 @@ export {
7879
8678
  AuthService,
7880
8679
  AuthTokenRequestBuilder,
7881
8680
  AuthorizationPermissionGrantBuilder,
8681
+ BATCH_MAX_PARTS,
8682
+ BATCH_MAX_PART_SIZE,
8683
+ BATCH_MAX_TOTAL_SIZE,
7882
8684
  Base64String,
8685
+ BatchFileBuilder,
7883
8686
  BatchSessionService,
7884
8687
  CERTIFICATE_NAME_MAX_LENGTH,
7885
8688
  CERTIFICATE_NAME_MIN_LENGTH,
@@ -7893,6 +8696,11 @@ export {
7893
8696
  ENFORCE_XADES_COMPLIANCE,
7894
8697
  EntityPermissionGrantBuilder,
7895
8698
  Environment,
8699
+ FORM_CODES,
8700
+ FORM_CODE_KEYS,
8701
+ FileHwmStore,
8702
+ INVOICE_TYPES_BY_SYSTEM_CODE,
8703
+ InMemoryHwmStore,
7896
8704
  InternalId,
7897
8705
  InvoiceDownloadService,
7898
8706
  InvoiceQueryFilterBuilder,
@@ -7938,21 +8746,29 @@ export {
7938
8746
  SessionStatusService,
7939
8747
  Sha256Base64,
7940
8748
  SignatureService,
8749
+ SystemCode,
7941
8750
  TestDataService,
7942
8751
  TokenService,
7943
8752
  UpoVersion,
7944
8753
  VatUe,
7945
8754
  VerificationLinkService,
7946
8755
  authenticateWithCertificate,
8756
+ authenticateWithExternalSignature,
7947
8757
  authenticateWithPkcs12,
7948
8758
  authenticateWithToken,
8759
+ buildUnsignedAuthTokenRequestXml,
7949
8760
  calculateBackoff,
8761
+ createZip,
8762
+ deduplicateByKsefNumber,
7950
8763
  defaultPresignedUrlPolicy,
7951
8764
  defaultRateLimitPolicy,
7952
8765
  defaultRetryPolicy,
7953
8766
  defaultTransport,
7954
8767
  exportAndDownload,
7955
8768
  exportInvoices,
8769
+ getEffectiveStartDate,
8770
+ getFormCode,
8771
+ incrementalExportAndDownload,
7956
8772
  isRetryableError,
7957
8773
  isRetryableStatus,
7958
8774
  isValidBase64,
@@ -7972,11 +8788,19 @@ export {
7972
8788
  isValidVatUe,
7973
8789
  openOnlineSession,
7974
8790
  openSendAndClose,
8791
+ parseFormCode,
7975
8792
  parseRetryAfter,
8793
+ parseUpoXml,
7976
8794
  pollUntil,
7977
8795
  resolveOptions,
7978
8796
  sleep,
8797
+ unzip,
8798
+ updateContinuationPoint,
7979
8799
  uploadBatch,
8800
+ uploadBatchParsed,
8801
+ uploadBatchStream,
8802
+ uploadBatchStreamParsed,
8803
+ validateFormCodeForSession,
7980
8804
  validatePresignedUrl
7981
8805
  };
7982
8806
  //# sourceMappingURL=index.js.map