facturas 0.4.2 → 0.5.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
@@ -24,10 +24,12 @@ var ArcaInputError = class extends ArcaError {
24
24
  var ArcaTransportError = class extends ArcaError {
25
25
  name = "ArcaTransportError";
26
26
  statusCode;
27
+ contentType;
27
28
  responseBody;
28
29
  constructor(message, options) {
29
30
  super(message, "ARCA_TRANSPORT_ERROR", options);
30
31
  this.statusCode = options?.statusCode;
32
+ this.contentType = options?.contentType;
31
33
  this.responseBody = options?.responseBody;
32
34
  }
33
35
  };
@@ -41,6 +43,28 @@ var ArcaSoapFaultError = class extends ArcaError {
41
43
  this.detail = options?.detail;
42
44
  }
43
45
  };
46
+ var ArcaInvalidSoapResponseError = class extends ArcaError {
47
+ name = "ArcaInvalidSoapResponseError";
48
+ service;
49
+ operation;
50
+ endpointUrl;
51
+ statusCode;
52
+ contentType;
53
+ responseBodyLength;
54
+ responseBodyPreview;
55
+ parsedDetail;
56
+ constructor(message, options) {
57
+ super(message, "ARCA_INVALID_SOAP_RESPONSE", options);
58
+ this.service = options?.service;
59
+ this.operation = options?.operation;
60
+ this.endpointUrl = options?.endpointUrl;
61
+ this.statusCode = options?.statusCode;
62
+ this.contentType = options?.contentType;
63
+ this.responseBodyLength = options?.responseBodyLength;
64
+ this.responseBodyPreview = options?.responseBodyPreview;
65
+ this.parsedDetail = options?.parsedDetail;
66
+ }
67
+ };
44
68
  var ArcaServiceError = class extends ArcaError {
45
69
  name = "ArcaServiceError";
46
70
  serviceCode;
@@ -125,12 +149,33 @@ function assertArcaClientConfig(config) {
125
149
  if (normalized.logger?.log !== void 0 && typeof normalized.logger.log !== "function") {
126
150
  invalidFields.push("logger.log");
127
151
  }
152
+ invalidFields.push(...getInvalidWsaaSessionStoreFields(normalized));
128
153
  if (invalidFields.length > 0) {
129
154
  throw new ArcaConfigurationError(
130
155
  `Missing or invalid ARCA client config fields: ${invalidFields.join(", ")}`
131
156
  );
132
157
  }
133
158
  }
159
+ function getInvalidWsaaSessionStoreFields(config) {
160
+ const store = config.wsaaSessionStore;
161
+ if (store === void 0) {
162
+ return [];
163
+ }
164
+ const invalidFields = [];
165
+ if (typeof store.get !== "function") {
166
+ invalidFields.push("wsaaSessionStore.get");
167
+ }
168
+ if (typeof store.set !== "function") {
169
+ invalidFields.push("wsaaSessionStore.set");
170
+ }
171
+ if (store.delete !== void 0 && typeof store.delete !== "function") {
172
+ invalidFields.push("wsaaSessionStore.delete");
173
+ }
174
+ if (store.withLock !== void 0 && typeof store.withLock !== "function") {
175
+ invalidFields.push("wsaaSessionStore.withLock");
176
+ }
177
+ return invalidFields;
178
+ }
134
179
  var ARCA_WSAA_CONFIG = {
135
180
  namespace: "http://wsaa.view.sua.dvadac.desein.afip.gov",
136
181
  endpoint: {
@@ -208,7 +253,8 @@ function normalizeArcaClientConfig(config) {
208
253
  ...config.logger,
209
254
  ...normalizedLoggerLevel === void 0 ? {} : { level: normalizedLoggerLevel }
210
255
  }
211
- }
256
+ },
257
+ ...config.wsaaSessionStore === void 0 ? {} : { wsaaSessionStore: config.wsaaSessionStore }
212
258
  };
213
259
  }
214
260
  function normalizeEnvironmentValue(value) {
@@ -1219,7 +1265,7 @@ var legacyTlsAgent = new https.Agent({
1219
1265
  keepAlive: true,
1220
1266
  ciphers: "DEFAULT@SECLEVEL=0"
1221
1267
  });
1222
- async function postXml({
1268
+ async function postXmlWithMetadata({
1223
1269
  url,
1224
1270
  body,
1225
1271
  contentType,
@@ -1287,12 +1333,12 @@ async function postXmlOnce({
1287
1333
  const requestBody = Buffer.from(body, "utf8");
1288
1334
  return await new Promise((resolve, reject) => {
1289
1335
  let settled = false;
1290
- const settleResolve = (responseBody) => {
1336
+ const settleResolve = (response) => {
1291
1337
  if (settled) {
1292
1338
  return;
1293
1339
  }
1294
1340
  settled = true;
1295
- resolve(responseBody);
1341
+ resolve(response);
1296
1342
  };
1297
1343
  const settleReject = (error) => {
1298
1344
  if (settled) {
@@ -1351,11 +1397,19 @@ async function postXmlOnce({
1351
1397
  response.headers["content-type"]
1352
1398
  ) ? response.headers["content-type"].join("; ") : response.headers["content-type"];
1353
1399
  if (statusCode >= 200 && statusCode < 300) {
1354
- settleResolve(responseBody);
1400
+ settleResolve({
1401
+ body: responseBody,
1402
+ statusCode,
1403
+ contentType: responseContentType
1404
+ });
1355
1405
  return;
1356
1406
  }
1357
1407
  if (isXmlLikeResponse(responseBody, responseContentType)) {
1358
- settleResolve(responseBody);
1408
+ settleResolve({
1409
+ body: responseBody,
1410
+ statusCode,
1411
+ contentType: responseContentType
1412
+ });
1359
1413
  return;
1360
1414
  }
1361
1415
  settleReject(
@@ -1363,6 +1417,7 @@ async function postXmlOnce({
1363
1417
  `ARCA HTTP request failed with status ${statusCode}`,
1364
1418
  {
1365
1419
  statusCode,
1420
+ contentType: responseContentType,
1366
1421
  responseBody
1367
1422
  }
1368
1423
  )
@@ -1437,14 +1492,26 @@ function buildSoapEnvelope(soapVersion, operation, namespace, body, options) {
1437
1492
  };
1438
1493
  return `<?xml version="1.0" encoding="utf-8"?>${xmlBuilder.build(payload)}`;
1439
1494
  }
1440
- function parseSoapBody(xml) {
1441
- const parsed = xmlParser.parse(xml);
1495
+ function parseSoapBody(xml, context = {}) {
1496
+ let parsed;
1497
+ try {
1498
+ parsed = xmlParser.parse(xml);
1499
+ } catch (error) {
1500
+ throw createInvalidSoapResponseError(
1501
+ "Invalid SOAP response: XML parse failed",
1502
+ context,
1503
+ void 0,
1504
+ error instanceof Error ? error : void 0
1505
+ );
1506
+ }
1442
1507
  const envelope = parsed.Envelope;
1443
1508
  const body = envelope?.Body;
1444
1509
  if (!body) {
1445
- throw new ArcaSoapFaultError("Invalid SOAP response: missing body", {
1446
- detail: parsed
1447
- });
1510
+ throw createInvalidSoapResponseError(
1511
+ "Invalid SOAP response: missing body",
1512
+ context,
1513
+ parsed
1514
+ );
1448
1515
  }
1449
1516
  const fault = body.Fault;
1450
1517
  if (fault) {
@@ -1452,18 +1519,40 @@ function parseSoapBody(xml) {
1452
1519
  }
1453
1520
  return body;
1454
1521
  }
1455
- function getSingleBodyEntry(body) {
1522
+ function getSingleBodyEntry(body, context = {}) {
1456
1523
  const entries = Object.entries(body).filter(([key]) => key !== "@_xmlns");
1457
1524
  if (entries.length !== 1) {
1458
- throw new ArcaSoapFaultError(
1525
+ throw createInvalidSoapResponseError(
1459
1526
  `Invalid SOAP response: expected a single body entry, got ${entries.length}`,
1460
- {
1461
- detail: body
1462
- }
1527
+ context,
1528
+ body
1463
1529
  );
1464
1530
  }
1465
1531
  return entries[0];
1466
1532
  }
1533
+ function createInvalidSoapResponseError(message, context, parsedDetail, cause) {
1534
+ const responseBody = context.responseBody ?? "";
1535
+ return new ArcaInvalidSoapResponseError(message, {
1536
+ cause,
1537
+ service: context.service,
1538
+ operation: context.operation,
1539
+ endpointUrl: context.endpointUrl,
1540
+ statusCode: context.statusCode,
1541
+ contentType: context.contentType,
1542
+ responseBodyLength: responseBody.length,
1543
+ responseBodyPreview: sanitizeSoapResponsePreview(
1544
+ responseBody,
1545
+ context.responseBodyPreviewLength
1546
+ ),
1547
+ parsedDetail
1548
+ });
1549
+ }
1550
+ function sanitizeSoapResponsePreview(responseBody, maxLength = 4096) {
1551
+ return responseBody.replace(
1552
+ /<((?:[A-Za-z_][\w.-]*:)?(?:Token|Sign))\b([^>]*)>[\s\S]*?<\/\1>/gi,
1553
+ (_match, tagName, attributes) => `<${tagName}${attributes}>[REDACTED]</${tagName}>`
1554
+ ).slice(0, maxLength);
1555
+ }
1467
1556
  function parseXmlDocument(xml) {
1468
1557
  return xmlParser.parse(xml);
1469
1558
  }
@@ -1522,7 +1611,7 @@ function createSoapTransport(options) {
1522
1611
  url
1523
1612
  });
1524
1613
  try {
1525
- const responseXml = await postXml({
1614
+ const response = await postXmlWithMetadata({
1526
1615
  url,
1527
1616
  body: xml,
1528
1617
  contentType,
@@ -1540,12 +1629,23 @@ function createSoapTransport(options) {
1540
1629
  operation: request.operation,
1541
1630
  durationMs: Date.now() - startedAt
1542
1631
  });
1543
- const soapBody = parseSoapBody(responseXml);
1544
- const [, result] = getSingleBodyEntry(soapBody);
1632
+ const parseContext = {
1633
+ service: request.service,
1634
+ operation: request.operation,
1635
+ endpointUrl: url,
1636
+ statusCode: response.statusCode,
1637
+ contentType: response.contentType,
1638
+ responseBody: response.body
1639
+ };
1640
+ const soapBody = parseSoapBody(response.body, parseContext);
1641
+ const [, result] = getSingleBodyEntry(
1642
+ soapBody,
1643
+ parseContext
1644
+ );
1545
1645
  return {
1546
1646
  service: request.service,
1547
1647
  operation: request.operation,
1548
- raw: responseXml,
1648
+ raw: response.body,
1549
1649
  result
1550
1650
  };
1551
1651
  } catch (error) {
@@ -1558,6 +1658,17 @@ function createSoapTransport(options) {
1558
1658
  error
1559
1659
  });
1560
1660
  }
1661
+ if (error instanceof ArcaInvalidSoapResponseError) {
1662
+ options.logger?.error("ARCA invalid SOAP response", {
1663
+ service: request.service,
1664
+ operation: request.operation,
1665
+ url,
1666
+ statusCode: error.statusCode,
1667
+ contentType: error.contentType,
1668
+ responseBodyLength: error.responseBodyLength,
1669
+ error
1670
+ });
1671
+ }
1561
1672
  throw error;
1562
1673
  }
1563
1674
  }
@@ -1567,48 +1678,117 @@ function createSoapTransport(options) {
1567
1678
  // src/wsaa/index.ts
1568
1679
  import { createHash } from "crypto";
1569
1680
  import forge from "node-forge";
1681
+
1682
+ // src/wsaa/session-store.ts
1683
+ var CREDENTIAL_EXPIRY_SAFETY_MARGIN_MS = 6e4;
1684
+ function createMemoryWsaaSessionStore() {
1685
+ const sessions = /* @__PURE__ */ new Map();
1686
+ const locks = /* @__PURE__ */ new Map();
1687
+ return {
1688
+ get(key) {
1689
+ const credentials = sessions.get(serializeWsaaSessionKey(key));
1690
+ if (!(credentials && isWsaaCredentialValid(credentials))) {
1691
+ return Promise.resolve(null);
1692
+ }
1693
+ return Promise.resolve({ ...credentials });
1694
+ },
1695
+ set(key, credentials) {
1696
+ sessions.set(serializeWsaaSessionKey(key), { ...credentials });
1697
+ return Promise.resolve();
1698
+ },
1699
+ delete(key) {
1700
+ sessions.delete(serializeWsaaSessionKey(key));
1701
+ return Promise.resolve();
1702
+ },
1703
+ async withLock(key, fn) {
1704
+ const lockKey = serializeWsaaSessionKey(key);
1705
+ const previous = locks.get(lockKey) ?? Promise.resolve();
1706
+ let release = () => void 0;
1707
+ const current = new Promise((resolve) => {
1708
+ release = resolve;
1709
+ });
1710
+ const queued = previous.catch(() => void 0).then(() => current);
1711
+ locks.set(lockKey, queued);
1712
+ await previous.catch(() => void 0);
1713
+ try {
1714
+ return await fn();
1715
+ } finally {
1716
+ release();
1717
+ if (locks.get(lockKey) === queued) {
1718
+ locks.delete(lockKey);
1719
+ }
1720
+ }
1721
+ }
1722
+ };
1723
+ }
1724
+ function serializeWsaaSessionKey(key) {
1725
+ return [key.environment, key.service, key.certificateFingerprint].join(":");
1726
+ }
1727
+ function isWsaaCredentialValid(credentials) {
1728
+ return new Date(credentials.expiresAt).getTime() - Date.now() > CREDENTIAL_EXPIRY_SAFETY_MARGIN_MS;
1729
+ }
1730
+
1731
+ // src/wsaa/index.ts
1570
1732
  function createWsaaAuthModule(options) {
1571
1733
  const cache = /* @__PURE__ */ new Map();
1572
1734
  const inFlight = /* @__PURE__ */ new Map();
1573
1735
  return {
1574
1736
  async login(service, authOptions = {}) {
1575
- const cacheKey = buildWsaaCacheKey(options.config, service);
1737
+ const sessionKey = buildWsaaSessionKey(options.config, service);
1738
+ const cacheKey = serializeWsaaSessionKey(sessionKey);
1576
1739
  const running = inFlight.get(cacheKey);
1577
1740
  if (running) {
1578
1741
  return running;
1579
1742
  }
1580
1743
  const loginPromise = (async () => {
1581
- if (!authOptions.forceRefresh) {
1582
- const cached = getCachedCredentials(cache, cacheKey);
1583
- if (cached) {
1584
- options.logger?.debug("Attempting WSAA login", {
1585
- service,
1586
- source: "cached"
1587
- });
1588
- return cached;
1589
- }
1590
- }
1591
- options.logger?.debug("Attempting WSAA login", {
1744
+ const reuse = await getReusableCredentials({
1745
+ config: options.config,
1746
+ cache,
1747
+ cacheKey,
1748
+ sessionKey,
1749
+ logger: options.logger,
1592
1750
  service,
1593
- source: "fresh"
1594
- });
1595
- const credentials = await requestCredentials(options.config, service, {
1596
- logger: options.logger
1751
+ allowStore: !authOptions.forceRefresh,
1752
+ allowCache: !authOptions.forceRefresh
1597
1753
  });
1598
- options.logger?.info("WSAA login succeeded", {
1754
+ if (reuse) {
1755
+ return reuse;
1756
+ }
1757
+ const refresh = () => refreshWsaaCredentials({
1758
+ config: options.config,
1759
+ cache,
1760
+ cacheKey,
1761
+ sessionKey,
1762
+ logger: options.logger,
1599
1763
  service,
1600
- expiresAt: credentials.expiresAt
1764
+ forceRefresh: authOptions.forceRefresh === true
1601
1765
  });
1602
- cache.set(cacheKey, credentials);
1603
- return credentials;
1766
+ if (options.config.wsaaSessionStore?.withLock) {
1767
+ return await withWsaaSessionStoreLock(
1768
+ options.config,
1769
+ sessionKey,
1770
+ service,
1771
+ refresh
1772
+ );
1773
+ }
1774
+ return await refresh();
1604
1775
  })();
1605
1776
  inFlight.set(cacheKey, loginPromise);
1606
1777
  try {
1607
1778
  return await loginPromise;
1608
1779
  } catch (error) {
1609
- if (!authOptions.forceRefresh && error instanceof ArcaSoapFaultError && error.faultCode === "ns1:coe.alreadyAuthenticated") {
1610
- const cached = getCachedCredentials(cache, cacheKey);
1611
- if (cached) {
1780
+ if (error instanceof ArcaSoapFaultError && error.faultCode === "ns1:coe.alreadyAuthenticated") {
1781
+ const recovered = await getReusableCredentials({
1782
+ config: options.config,
1783
+ cache,
1784
+ cacheKey,
1785
+ sessionKey,
1786
+ logger: options.logger,
1787
+ service,
1788
+ allowStore: true,
1789
+ allowCache: true
1790
+ });
1791
+ if (recovered) {
1612
1792
  options.logger?.warn(
1613
1793
  "Recovered WSAA coe.alreadyAuthenticated fault",
1614
1794
  {
@@ -1616,7 +1796,13 @@ function createWsaaAuthModule(options) {
1616
1796
  faultCode: error.faultCode
1617
1797
  }
1618
1798
  );
1619
- return cached;
1799
+ return recovered;
1800
+ }
1801
+ if (!options.config.wsaaSessionStore) {
1802
+ throw new ArcaConfigurationError(
1803
+ "WSAA login failed because another process likely owns a valid TA. Configure a durable wsaaSessionStore for multi-process or serverless deployments.",
1804
+ { cause: error }
1805
+ );
1620
1806
  }
1621
1807
  }
1622
1808
  if (error instanceof ArcaSoapFaultError) {
@@ -1647,7 +1833,8 @@ async function requestCredentials(config, service, options) {
1647
1833
  ARCA_WSAA_CONFIG.namespace,
1648
1834
  { in0: signedCms }
1649
1835
  );
1650
- const responseXml = await postXml({
1836
+ const url = ARCA_WSAA_CONFIG.endpoint[config.environment];
1837
+ const response = await postXmlWithMetadata({
1651
1838
  url: ARCA_WSAA_CONFIG.endpoint[config.environment],
1652
1839
  body: requestXml,
1653
1840
  contentType: 'text/xml; charset="utf-8"',
@@ -1659,9 +1846,20 @@ async function requestCredentials(config, service, options) {
1659
1846
  service: "wsaa",
1660
1847
  operation: "loginCms"
1661
1848
  });
1662
- const soapBody = parseSoapBody(responseXml);
1663
- const [, response] = getSingleBodyEntry(soapBody);
1664
- const loginCmsReturn = response.loginCmsReturn;
1849
+ const parseContext = {
1850
+ service: "wsaa",
1851
+ operation: "loginCms",
1852
+ endpointUrl: url,
1853
+ statusCode: response.statusCode,
1854
+ contentType: response.contentType,
1855
+ responseBody: response.body
1856
+ };
1857
+ const soapBody = parseSoapBody(response.body, parseContext);
1858
+ const [, responseBody] = getSingleBodyEntry(
1859
+ soapBody,
1860
+ parseContext
1861
+ );
1862
+ const loginCmsReturn = responseBody.loginCmsReturn;
1665
1863
  if (typeof loginCmsReturn !== "string" || loginCmsReturn.trim().length < 1) {
1666
1864
  throw new ArcaTransportError(
1667
1865
  "WSAA response did not include loginCmsReturn XML"
@@ -1669,24 +1867,141 @@ async function requestCredentials(config, service, options) {
1669
1867
  }
1670
1868
  return parseLoginTicketResponse(loginCmsReturn);
1671
1869
  }
1672
- function buildWsaaCacheKey(config, service) {
1673
- return [config.environment, service, getCertificateFingerprint(config)].join(
1674
- ":"
1675
- );
1870
+ function buildWsaaSessionKey(config, service) {
1871
+ return {
1872
+ environment: config.environment,
1873
+ service,
1874
+ certificateFingerprint: getCertificateFingerprint(config)
1875
+ };
1676
1876
  }
1677
1877
  function getCertificateFingerprint(config) {
1678
1878
  return createHash("sha256").update(config.certificatePem).digest("hex");
1679
1879
  }
1680
- function isCredentialValid(credentials) {
1681
- return new Date(credentials.expiresAt).getTime() - Date.now() > 6e4;
1682
- }
1683
1880
  function getCachedCredentials(cache, cacheKey) {
1684
1881
  const localCached = cache.get(cacheKey);
1685
- if (localCached && isCredentialValid(localCached)) {
1882
+ if (localCached && isWsaaCredentialValid(localCached)) {
1686
1883
  return localCached;
1687
1884
  }
1688
1885
  return null;
1689
1886
  }
1887
+ async function getReusableCredentials(options) {
1888
+ if (options.allowCache) {
1889
+ const cached = getCachedCredentials(options.cache, options.cacheKey);
1890
+ if (cached) {
1891
+ options.logger?.debug("Attempting WSAA login", {
1892
+ service: options.service,
1893
+ source: "cached"
1894
+ });
1895
+ return cached;
1896
+ }
1897
+ }
1898
+ if (!(options.allowStore && options.config.wsaaSessionStore)) {
1899
+ return null;
1900
+ }
1901
+ const stored = await getStoredCredentials(
1902
+ options.config,
1903
+ options.sessionKey,
1904
+ options.service
1905
+ );
1906
+ if (!stored) {
1907
+ return null;
1908
+ }
1909
+ options.cache.set(options.cacheKey, stored);
1910
+ options.logger?.debug("Attempting WSAA login", {
1911
+ service: options.service,
1912
+ source: "store"
1913
+ });
1914
+ return stored;
1915
+ }
1916
+ async function refreshWsaaCredentials(options) {
1917
+ if (!options.forceRefresh) {
1918
+ const reuse = await getReusableCredentials({
1919
+ config: options.config,
1920
+ cache: options.cache,
1921
+ cacheKey: options.cacheKey,
1922
+ sessionKey: options.sessionKey,
1923
+ logger: options.logger,
1924
+ service: options.service,
1925
+ allowStore: true,
1926
+ allowCache: true
1927
+ });
1928
+ if (reuse) {
1929
+ return reuse;
1930
+ }
1931
+ }
1932
+ options.logger?.debug("Attempting WSAA login", {
1933
+ service: options.service,
1934
+ source: "fresh"
1935
+ });
1936
+ const credentials = await requestCredentials(
1937
+ options.config,
1938
+ options.service,
1939
+ {
1940
+ logger: options.logger
1941
+ }
1942
+ );
1943
+ options.logger?.info("WSAA login succeeded", {
1944
+ service: options.service,
1945
+ expiresAt: credentials.expiresAt
1946
+ });
1947
+ options.cache.set(options.cacheKey, credentials);
1948
+ await setStoredCredentials(options.config, options.sessionKey, credentials);
1949
+ return credentials;
1950
+ }
1951
+ async function getStoredCredentials(config, key, service) {
1952
+ if (!config.wsaaSessionStore) {
1953
+ return null;
1954
+ }
1955
+ try {
1956
+ const credentials = await config.wsaaSessionStore.get(key);
1957
+ if (!(credentials && isWsaaCredentialValid(credentials))) {
1958
+ return null;
1959
+ }
1960
+ return credentials;
1961
+ } catch (error) {
1962
+ throw new ArcaConfigurationError(
1963
+ `WSAA session store get failed for service ${service}`,
1964
+ { cause: error instanceof Error ? error : void 0 }
1965
+ );
1966
+ }
1967
+ }
1968
+ async function setStoredCredentials(config, key, credentials) {
1969
+ if (!config.wsaaSessionStore) {
1970
+ return;
1971
+ }
1972
+ try {
1973
+ await config.wsaaSessionStore.set(key, credentials);
1974
+ } catch (error) {
1975
+ throw new ArcaConfigurationError(
1976
+ `WSAA session store set failed for service ${key.service}`,
1977
+ { cause: error instanceof Error ? error : void 0 }
1978
+ );
1979
+ }
1980
+ }
1981
+ async function withWsaaSessionStoreLock(config, key, service, fn) {
1982
+ const store = config.wsaaSessionStore;
1983
+ if (!store?.withLock) {
1984
+ return await fn();
1985
+ }
1986
+ let entered = false;
1987
+ try {
1988
+ return await store.withLock(key, async () => {
1989
+ entered = true;
1990
+ return await fn();
1991
+ });
1992
+ } catch (error) {
1993
+ if (entered) {
1994
+ throw error;
1995
+ }
1996
+ if (error instanceof ArcaConfigurationError) {
1997
+ throw error;
1998
+ }
1999
+ throw new ArcaConfigurationError(
2000
+ `WSAA session store lock failed for service ${service}`,
2001
+ { cause: error instanceof Error ? error : void 0 }
2002
+ );
2003
+ }
2004
+ }
1690
2005
  function buildLoginTicketRequest(service) {
1691
2006
  const uniqueId = Math.floor(Date.now() / 1e3);
1692
2007
  const generationTime = new Date(Date.now() - 5 * 6e4).toISOString().replace(".000Z", "Z");
@@ -1771,12 +2086,14 @@ export {
1771
2086
  ArcaConfigurationError,
1772
2087
  ArcaError,
1773
2088
  ArcaInputError,
2089
+ ArcaInvalidSoapResponseError,
1774
2090
  ArcaServiceError,
1775
2091
  ArcaSoapFaultError,
1776
2092
  ArcaTransportError,
1777
2093
  assertArcaClientConfig,
1778
2094
  createArcaClient,
1779
2095
  createArcaClientConfigFromEnv,
2096
+ createMemoryWsaaSessionStore,
1780
2097
  createPadronService,
1781
2098
  createWsfeService,
1782
2099
  createWsmtxcaService,