facturas 0.7.1 → 0.8.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/README.md CHANGED
@@ -29,10 +29,22 @@ The package exports:
29
29
  - `facturas/errors`
30
30
  - `facturas/types`
31
31
 
32
- The primary WSFE path uses `buildFacturaB()` or `buildFacturaC()` with integer
33
- minor-unit amounts and ISO `ARS`/`USD` currency input. The builders are exported
34
- from both `facturas` and `facturas/wsfe`. Advanced exact `WsfeVoucherInput`
35
- requests continue to use ARCA currency identifiers such as `PES` and `DOL`.
32
+ The primary invoice path is `client.vouchers.issue()`, using an explicit
33
+ `issuer`, a fiscal `to` receiver, a required `salesPoint`, and integer-minor-unit
34
+ items. It derives A/B/C, VAT and totals, and returns `authorized`, `rejected`,
35
+ `indeterminate`, or `conflict`. Raw provider evidence is opt-in.
36
+
37
+ **Single-writer contract:** serialize per `(representedTaxId, salesPoint,
38
+ voucherType)`. The SDK does not coordinate writers; concurrent calls collide on
39
+ 10016. Servers and queues must persist attempts and use
40
+ `client.wsfe.authorizeVoucherOutcome()` directly. The facade makes one write
41
+ attempt and at most one identity-matched recovery lookup, never a resubmission.
42
+
43
+ `buildFacturaB()` and `buildFacturaC()` retain their v0.7.1 behavior and are
44
+ exported from `facturas` and `facturas/wsfe`. The facade and builders accept ISO
45
+ `ARS`/`USD`; exact `WsfeVoucherInput` uses provider identifiers `PES`/`DOL`.
46
+ The only existing type widening in v0.8 is required `ArcaClient.vouchers`;
47
+ hand-built typed mocks must add that member.
36
48
 
37
49
  `facturas` also exports `createMemoryWsaaSessionStore()` for tests/local single-process coordination and the small `ArcaWsaaSessionStore` interface for applications that need to share WSAA tickets across workers through their own durable store.
38
50
 
@@ -0,0 +1,109 @@
1
+ // src/constants.ts
2
+ var ARCA_VOUCHER_TYPES = {
3
+ FACTURA_A: 1,
4
+ NOTA_DEBITO_A: 2,
5
+ NOTA_CREDITO_A: 3,
6
+ FACTURA_B: 6,
7
+ NOTA_DEBITO_B: 7,
8
+ NOTA_CREDITO_B: 8,
9
+ FACTURA_C: 11,
10
+ NOTA_DEBITO_C: 12,
11
+ NOTA_CREDITO_C: 13
12
+ };
13
+ var ARCA_DOCUMENT_TYPES = {
14
+ CUIT: 80,
15
+ DNI: 96,
16
+ CONSUMIDOR_FINAL: 99
17
+ };
18
+ var ARCA_RECEIVER_VAT_CONDITIONS = {
19
+ RESPONSABLE_INSCRIPTO: 1,
20
+ EXENTO: 4,
21
+ CONSUMIDOR_FINAL: 5,
22
+ MONOTRIBUTISTA: 6,
23
+ IVA_NO_ALCANZADO: 15
24
+ };
25
+ var ARCA_CONCEPT_TYPES = {
26
+ PRODUCTOS: 1,
27
+ SERVICIOS: 2,
28
+ PRODUCTOS_Y_SERVICIOS: 3
29
+ };
30
+ var ARCA_VAT_RATES = {
31
+ IVA_0: 3,
32
+ IVA_10_5: 4,
33
+ IVA_21: 5,
34
+ IVA_27: 6,
35
+ IVA_5: 8,
36
+ IVA_2_5: 9
37
+ };
38
+ var ISO_CURRENCIES = {
39
+ ARS: "ARS",
40
+ USD: "USD"
41
+ };
42
+ var ARCA_CURRENCY_IDS = {
43
+ ARS: "PES",
44
+ USD: "DOL"
45
+ };
46
+ var ARCA_CURRENCIES = {
47
+ PES: "PES",
48
+ DOL: "DOL"
49
+ };
50
+ var ARCA_RECEIVER_CONDITION_IDS = {
51
+ responsable_inscripto: ARCA_RECEIVER_VAT_CONDITIONS.RESPONSABLE_INSCRIPTO,
52
+ monotributo: ARCA_RECEIVER_VAT_CONDITIONS.MONOTRIBUTISTA,
53
+ exento: ARCA_RECEIVER_VAT_CONDITIONS.EXENTO,
54
+ consumidor_final: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,
55
+ no_alcanzado: ARCA_RECEIVER_VAT_CONDITIONS.IVA_NO_ALCANZADO
56
+ };
57
+ var ARCA_ISSUER_CONDITION_IDS = {
58
+ responsable_inscripto: 1,
59
+ monotributo: 6,
60
+ exento: 4,
61
+ no_alcanzado: 15
62
+ };
63
+ var ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS = 1000000000n;
64
+ var ARCA_INVOICE_CLASS_BY_ISSUER = {
65
+ responsable_inscripto: {
66
+ responsable_inscripto: "A",
67
+ monotributo: "A",
68
+ exento: "B",
69
+ consumidor_final: "B",
70
+ no_alcanzado: "B"
71
+ },
72
+ monotributo: {
73
+ responsable_inscripto: "C",
74
+ monotributo: "C",
75
+ exento: "C",
76
+ consumidor_final: "C",
77
+ no_alcanzado: "C"
78
+ },
79
+ exento: {
80
+ responsable_inscripto: "C",
81
+ monotributo: "C",
82
+ exento: "C",
83
+ consumidor_final: "C",
84
+ no_alcanzado: "C"
85
+ },
86
+ no_alcanzado: {
87
+ responsable_inscripto: "C",
88
+ monotributo: "C",
89
+ exento: "C",
90
+ consumidor_final: "C",
91
+ no_alcanzado: "C"
92
+ }
93
+ };
94
+
95
+ export {
96
+ ARCA_VOUCHER_TYPES,
97
+ ARCA_DOCUMENT_TYPES,
98
+ ARCA_RECEIVER_VAT_CONDITIONS,
99
+ ARCA_CONCEPT_TYPES,
100
+ ARCA_VAT_RATES,
101
+ ISO_CURRENCIES,
102
+ ARCA_CURRENCY_IDS,
103
+ ARCA_CURRENCIES,
104
+ ARCA_RECEIVER_CONDITION_IDS,
105
+ ARCA_ISSUER_CONDITION_IDS,
106
+ ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS,
107
+ ARCA_INVOICE_CLASS_BY_ISSUER
108
+ };
109
+ //# sourceMappingURL=chunk-76WU5BVI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/** Common ARCA reference data for readable userland code and examples. */\nexport const ARCA_VOUCHER_TYPES = {\n FACTURA_A: 1,\n NOTA_DEBITO_A: 2,\n NOTA_CREDITO_A: 3,\n FACTURA_B: 6,\n NOTA_DEBITO_B: 7,\n NOTA_CREDITO_B: 8,\n FACTURA_C: 11,\n NOTA_DEBITO_C: 12,\n NOTA_CREDITO_C: 13,\n} as const;\n\n/** Common document types accepted by ARCA services. */\nexport const ARCA_DOCUMENT_TYPES = {\n CUIT: 80,\n DNI: 96,\n CONSUMIDOR_FINAL: 99,\n} as const;\n\n/**\n * Common receiver IVA condition identifiers used by WSFE.\n * Allowed values depend on the voucher class and ARCA's live catalog.\n */\nexport const ARCA_RECEIVER_VAT_CONDITIONS = {\n RESPONSABLE_INSCRIPTO: 1,\n EXENTO: 4,\n CONSUMIDOR_FINAL: 5,\n MONOTRIBUTISTA: 6,\n IVA_NO_ALCANZADO: 15,\n} as const;\n\n/** Supported invoice concept types for WSFE requests. */\nexport const ARCA_CONCEPT_TYPES = {\n PRODUCTOS: 1,\n SERVICIOS: 2,\n PRODUCTOS_Y_SERVICIOS: 3,\n} as const;\n\n/** Common IVA rate identifiers used by WSFE. */\nexport const ARCA_VAT_RATES = {\n IVA_0: 3,\n IVA_10_5: 4,\n IVA_21: 5,\n IVA_27: 6,\n IVA_5: 8,\n IVA_2_5: 9,\n} as const;\n\n/** ISO currency codes accepted by the high-level WSFE builders. */\nexport const ISO_CURRENCIES = {\n ARS: \"ARS\",\n USD: \"USD\",\n} as const;\n\n/** ARCA currency identifiers keyed by their corresponding ISO currency. */\nexport const ARCA_CURRENCY_IDS = {\n ARS: \"PES\",\n USD: \"DOL\",\n} as const;\n\n/**\n * Common ARCA currency identifiers.\n * @deprecated Use ISO_CURRENCIES for builders or ARCA_CURRENCY_IDS at the exact provider boundary.\n */\nexport const ARCA_CURRENCIES = {\n PES: \"PES\",\n DOL: \"DOL\",\n} as const;\n\n/** Legal assertions supported by the invoice facade; never inferred from Padrón. */\nexport type IssuerCondition =\n | \"responsable_inscripto\"\n | \"monotributo\"\n | \"exento\"\n | \"no_alcanzado\";\nexport type ReceiverCondition = IssuerCondition | \"consumidor_final\";\nexport type VoucherClass = \"A\" | \"B\" | \"C\";\n\nexport const ARCA_RECEIVER_CONDITION_IDS = {\n responsable_inscripto: ARCA_RECEIVER_VAT_CONDITIONS.RESPONSABLE_INSCRIPTO,\n monotributo: ARCA_RECEIVER_VAT_CONDITIONS.MONOTRIBUTISTA,\n exento: ARCA_RECEIVER_VAT_CONDITIONS.EXENTO,\n consumidor_final: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,\n no_alcanzado: ARCA_RECEIVER_VAT_CONDITIONS.IVA_NO_ALCANZADO,\n} as const satisfies Record<ReceiverCondition, number>;\n\nexport const ARCA_ISSUER_CONDITION_IDS = {\n responsable_inscripto: 1,\n monotributo: 6,\n exento: 4,\n no_alcanzado: 15,\n} as const satisfies Record<IssuerCondition, number>;\n\n// RG 5866/2026, art. 1(f), effective 2026-07-01 (art. 4).\n// https://www.argentina.gob.ar/normativa/nacional/norma-427092/texto\nexport const ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS =\n 1_000_000_000n;\n\n// WSFE v4.7, physical PDF p. 203, validations 10243/10246; issuer asserted first.\n// ARCA checks actual issuer eligibility independently at authorization.\nexport const ARCA_INVOICE_CLASS_BY_ISSUER = {\n responsable_inscripto: {\n responsable_inscripto: \"A\",\n monotributo: \"A\",\n exento: \"B\",\n consumidor_final: \"B\",\n no_alcanzado: \"B\",\n },\n monotributo: {\n responsable_inscripto: \"C\",\n monotributo: \"C\",\n exento: \"C\",\n consumidor_final: \"C\",\n no_alcanzado: \"C\",\n },\n exento: {\n responsable_inscripto: \"C\",\n monotributo: \"C\",\n exento: \"C\",\n consumidor_final: \"C\",\n no_alcanzado: \"C\",\n },\n no_alcanzado: {\n responsable_inscripto: \"C\",\n monotributo: \"C\",\n exento: \"C\",\n consumidor_final: \"C\",\n no_alcanzado: \"C\",\n },\n} as const satisfies Record<\n IssuerCondition,\n Record<ReceiverCondition, VoucherClass>\n>;\n"],"mappings":";AACO,IAAM,qBAAqB;AAAA,EAChC,WAAW;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAClB;AAGO,IAAM,sBAAsB;AAAA,EACjC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,kBAAkB;AACpB;AAMO,IAAM,+BAA+B;AAAA,EAC1C,uBAAuB;AAAA,EACvB,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,kBAAkB;AACpB;AAGO,IAAM,qBAAqB;AAAA,EAChC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,uBAAuB;AACzB;AAGO,IAAM,iBAAiB;AAAA,EAC5B,OAAO;AAAA,EACP,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AACX;AAGO,IAAM,iBAAiB;AAAA,EAC5B,KAAK;AAAA,EACL,KAAK;AACP;AAGO,IAAM,oBAAoB;AAAA,EAC/B,KAAK;AAAA,EACL,KAAK;AACP;AAMO,IAAM,kBAAkB;AAAA,EAC7B,KAAK;AAAA,EACL,KAAK;AACP;AAWO,IAAM,8BAA8B;AAAA,EACzC,uBAAuB,6BAA6B;AAAA,EACpD,aAAa,6BAA6B;AAAA,EAC1C,QAAQ,6BAA6B;AAAA,EACrC,kBAAkB,6BAA6B;AAAA,EAC/C,cAAc,6BAA6B;AAC7C;AAEO,IAAM,4BAA4B;AAAA,EACvC,uBAAuB;AAAA,EACvB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,cAAc;AAChB;AAIO,IAAM,2DACX;AAIK,IAAM,+BAA+B;AAAA,EAC1C,uBAAuB;AAAA,IACrB,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AAAA,EACA,aAAa;AAAA,IACX,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AAAA,EACA,QAAQ;AAAA,IACN,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AAAA,EACA,cAAc;AAAA,IACZ,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AACF;","names":[]}
@@ -198,6 +198,17 @@ function normalizeProviderCode(providerCode) {
198
198
  }
199
199
  return void 0;
200
200
  }
201
+ function toArcaSafeErrorMetadata(error) {
202
+ if (!(error instanceof Error)) {
203
+ return { name: "UnknownError", message: String(error) };
204
+ }
205
+ return {
206
+ name: error.name,
207
+ message: error.message,
208
+ ...error instanceof ArcaError ? { code: error.code } : {},
209
+ ...error instanceof ArcaTransportError && error.statusCode !== void 0 ? { statusCode: error.statusCode } : {}
210
+ };
211
+ }
201
212
 
202
213
  export {
203
214
  createResponseBodyDiagnostic,
@@ -210,6 +221,7 @@ export {
210
221
  ArcaTransportError,
211
222
  ArcaSoapFaultError,
212
223
  ArcaInvalidSoapResponseError,
213
- ArcaServiceError
224
+ ArcaServiceError,
225
+ toArcaSafeErrorMetadata
214
226
  };
215
- //# sourceMappingURL=chunk-MBWOFO67.mjs.map
227
+ //# sourceMappingURL=chunk-HUT3PFKF.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/redaction.ts","../src/errors.ts"],"sourcesContent":["export const MAX_DIAGNOSTIC_PREVIEW_LENGTH = 4096;\n\nconst MAX_DIAGNOSTIC_SCALAR_LENGTH = 512;\nconst SENSITIVE_XML_ELEMENT_NAME = \"((?:[A-Za-z_][\\\\w.-]*:)?(?:Token|Sign))\";\nconst PAIRED_SENSITIVE_XML_ELEMENT = new RegExp(\n `<${SENSITIVE_XML_ELEMENT_NAME}\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\/\\\\1\\\\s*>`,\n \"gi\"\n);\nconst SELF_CLOSING_SENSITIVE_XML_ELEMENT = new RegExp(\n `<${SENSITIVE_XML_ELEMENT_NAME}\\\\b[^>]*\\\\/\\\\s*>`,\n \"gi\"\n);\nconst UNTERMINATED_SENSITIVE_XML_ELEMENT = new RegExp(\n `<${SENSITIVE_XML_ELEMENT_NAME}\\\\b[^>]*>[^<]*`,\n \"gi\"\n);\n\nexport type ResponseBodyDiagnostic = {\n responseBodyLength: number;\n responseBodyPreview: string;\n};\n\nexport type SafeErrorDiagnostic = {\n errorName?: string;\n errorCode?: string;\n statusCode?: number;\n contentType?: string;\n responseBodyLength?: number;\n responseBodyPreview?: string;\n faultCode?: string;\n};\n\n/** Redacts credential-bearing XML elements and applies the global preview bound. */\nexport function redactDiagnosticPreview(\n value: string,\n requestedMaxLength = MAX_DIAGNOSTIC_PREVIEW_LENGTH\n): string {\n const maxLength = normalizePreviewLength(requestedMaxLength);\n\n return value\n .replace(\n PAIRED_SENSITIVE_XML_ELEMENT,\n (_match, tagName: string) => `<${tagName}>[REDACTED]</${tagName}>`\n )\n .replace(\n SELF_CLOSING_SENSITIVE_XML_ELEMENT,\n (_match, tagName: string) => `<${tagName}>[REDACTED]</${tagName}>`\n )\n .replace(\n UNTERMINATED_SENSITIVE_XML_ELEMENT,\n (_match, tagName: string) => `<${tagName}>[REDACTED]`\n )\n .slice(0, maxLength);\n}\n\n/** Produces the only response-body shape allowed in errors and logs. */\nexport function createResponseBodyDiagnostic(\n responseBody: string,\n requestedMaxLength = MAX_DIAGNOSTIC_PREVIEW_LENGTH\n): ResponseBodyDiagnostic {\n return {\n responseBodyLength: responseBody.length,\n responseBodyPreview: redactDiagnosticPreview(\n responseBody,\n requestedMaxLength\n ),\n };\n}\n\n/** Extracts a scalar allowlist from an error without exposing the error or cause. */\nexport function createSafeErrorDiagnostic(error: unknown): SafeErrorDiagnostic {\n if (!(error && typeof error === \"object\")) {\n return {};\n }\n\n const candidate = error as Record<string, unknown>;\n const diagnostic: SafeErrorDiagnostic = {};\n\n assignSafeString(diagnostic, \"errorName\", candidate.name);\n assignSafeString(diagnostic, \"errorCode\", candidate.code);\n assignSafeNumber(diagnostic, \"statusCode\", candidate.statusCode);\n assignSafeString(diagnostic, \"contentType\", candidate.contentType);\n assignSafeNumber(\n diagnostic,\n \"responseBodyLength\",\n candidate.responseBodyLength\n );\n if (typeof candidate.responseBodyPreview === \"string\") {\n diagnostic.responseBodyPreview = redactDiagnosticPreview(\n candidate.responseBodyPreview\n );\n }\n assignSafeString(diagnostic, \"faultCode\", candidate.faultCode);\n\n return diagnostic;\n}\n\nfunction normalizePreviewLength(requestedMaxLength: number): number {\n if (!Number.isFinite(requestedMaxLength)) {\n return MAX_DIAGNOSTIC_PREVIEW_LENGTH;\n }\n\n return Math.max(\n 0,\n Math.min(Math.trunc(requestedMaxLength), MAX_DIAGNOSTIC_PREVIEW_LENGTH)\n );\n}\n\nfunction assignSafeString<\n TKey extends \"errorName\" | \"errorCode\" | \"contentType\" | \"faultCode\",\n>(target: SafeErrorDiagnostic, key: TKey, value: unknown): void {\n if (typeof value === \"string\") {\n target[key] = redactDiagnosticPreview(value, MAX_DIAGNOSTIC_SCALAR_LENGTH);\n }\n}\n\nfunction assignSafeNumber<TKey extends \"statusCode\" | \"responseBodyLength\">(\n target: SafeErrorDiagnostic,\n key: TKey,\n value: unknown\n): void {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n target[key] = value;\n }\n}\n","import { redactDiagnosticPreview } from \"./internal/redaction\";\nimport type { ArcaServiceName } from \"./internal/types\";\nimport type {\n ArcaFiscalIssue,\n ArcaFiscalResultLevel,\n ArcaFiscalResults,\n} from \"./services/fiscal-evidence\";\n\n/** Base error class for all ARCA-related errors. */\nexport class ArcaError extends Error {\n readonly code: string;\n override readonly name: string = \"ArcaError\";\n\n constructor(message: string, code = \"ARCA_ERROR\", options?: ErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** Thrown when the ARCA client configuration is missing or invalid. */\nexport class ArcaConfigurationError extends ArcaError {\n override readonly name: string = \"ArcaConfigurationError\";\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, \"ARCA_CONFIGURATION_ERROR\", options);\n }\n}\n\n/** Stable routing codes for caller-provided input failures. */\nexport type ArcaInputErrorCode =\n | \"ARCA_INPUT_INVALID_DATE\"\n | \"ARCA_INPUT_INVALID_AMOUNT\"\n | \"ARCA_INPUT_AMOUNT_PRECISION\"\n | \"ARCA_INPUT_AMOUNT_MISMATCH\"\n | \"ARCA_INPUT_INVALID_EXCHANGE_RATE\"\n | \"ARCA_INPUT_INVALID_VALUE\"\n | \"ARCA_INPUT_MISSING_FIELD\"\n | \"ARCA_INPUT_RESERVED_FIELD\";\n\nexport type ArcaInputErrorOptions = ErrorOptions & {\n code: ArcaInputErrorCode;\n field?: string;\n expected?: string;\n};\n\n/** Thrown when caller-provided input data is missing or invalid. */\nexport class ArcaInputError extends ArcaError {\n declare readonly code: ArcaInputErrorCode;\n override readonly name: string = \"ArcaInputError\";\n readonly field?: string;\n readonly expected?: string;\n\n constructor(message: string, options: ArcaInputErrorOptions) {\n super(message, options.code, options);\n this.field = options.field;\n this.expected = options.expected;\n }\n}\n\n/** Stable reasons exposed for explicit ARCA authentication rejections. */\nexport type ArcaAuthenticationReason =\n | \"invalid_token\"\n | \"unauthorized_computer\"\n | \"missing_relationship\"\n | \"authentication_rejected\";\n\nexport type ArcaAuthenticationErrorOptions = ErrorOptions & {\n reason: ArcaAuthenticationReason;\n service: ArcaServiceName;\n operation: string;\n providerCode?: string | number;\n};\n\n/** Thrown when ARCA explicitly rejects credentials before an operation runs. */\nexport class ArcaAuthenticationError extends ArcaError {\n declare readonly code: \"ARCA_AUTHENTICATION_ERROR\";\n override readonly name: string = \"ArcaAuthenticationError\";\n readonly reason: ArcaAuthenticationReason;\n readonly service: ArcaServiceName;\n readonly operation: string;\n readonly providerCode?: string | number;\n\n constructor(message: string, options: ArcaAuthenticationErrorOptions) {\n super(\n redactDiagnosticPreview(message),\n \"ARCA_AUTHENTICATION_ERROR\",\n options\n );\n this.reason = options.reason;\n this.service = options.service;\n this.operation = options.operation;\n this.providerCode = normalizeProviderCode(options.providerCode);\n }\n}\n\n/** Narrows unknown failures to the explicit authentication error contract. */\nexport function isArcaAuthenticationError(\n error: unknown\n): error is ArcaAuthenticationError {\n return error instanceof ArcaAuthenticationError;\n}\n\n/** Thrown when an HTTP request to an ARCA endpoint fails at the transport level. */\nexport class ArcaTransportError extends ArcaError {\n override readonly name: string = \"ArcaTransportError\";\n readonly statusCode?: number;\n readonly contentType?: string;\n readonly responseBodyLength?: number;\n readonly responseBodyPreview?: string;\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n statusCode?: number;\n contentType?: string;\n responseBodyLength?: number;\n responseBodyPreview?: string;\n }\n ) {\n super(message, \"ARCA_TRANSPORT_ERROR\", options);\n this.statusCode = options?.statusCode;\n this.contentType = options?.contentType;\n this.responseBodyLength = options?.responseBodyLength;\n this.responseBodyPreview =\n options?.responseBodyPreview === undefined\n ? undefined\n : redactDiagnosticPreview(options.responseBodyPreview);\n }\n}\n\n/** Thrown when the SOAP response contains a Fault element. */\nexport class ArcaSoapFaultError extends ArcaError {\n override readonly name: string = \"ArcaSoapFaultError\";\n readonly faultCode?: string;\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n faultCode?: string;\n }\n ) {\n super(redactDiagnosticPreview(message), \"ARCA_SOAP_FAULT\", options);\n this.faultCode =\n options?.faultCode === undefined\n ? undefined\n : redactDiagnosticPreview(options.faultCode);\n }\n}\n\n/** Thrown when a response cannot be parsed as a valid SOAP envelope. */\nexport class ArcaInvalidSoapResponseError extends ArcaError {\n override readonly name: string = \"ArcaInvalidSoapResponseError\";\n readonly service?: ArcaServiceName;\n readonly operation?: string;\n readonly endpointUrl?: string;\n readonly statusCode?: number;\n readonly contentType?: string;\n readonly responseBodyLength?: number;\n readonly responseBodyPreview?: string;\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n service?: ArcaServiceName;\n operation?: string;\n endpointUrl?: string;\n statusCode?: number;\n contentType?: string;\n responseBodyLength?: number;\n responseBodyPreview?: string;\n }\n ) {\n super(message, \"ARCA_INVALID_SOAP_RESPONSE\", options);\n this.service = options?.service;\n this.operation = options?.operation;\n this.endpointUrl = options?.endpointUrl;\n this.statusCode = options?.statusCode;\n this.contentType = options?.contentType;\n this.responseBodyLength = options?.responseBodyLength;\n this.responseBodyPreview =\n options?.responseBodyPreview === undefined\n ? undefined\n : redactDiagnosticPreview(options.responseBodyPreview);\n }\n}\n\n/** Thrown when an ARCA service (WSFE, WSMTXCA, Padron) returns a domain-level error. */\nexport class ArcaServiceError extends ArcaError {\n override readonly name: string = \"ArcaServiceError\";\n readonly serviceCode?: string | number;\n readonly service?: ArcaServiceName;\n readonly operation?: string;\n readonly result?: string;\n readonly resultLevel?: ArcaFiscalResultLevel;\n readonly results?: ArcaFiscalResults;\n readonly cae?: string;\n readonly issues?: readonly ArcaFiscalIssue[];\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n serviceCode?: string | number;\n service?: ArcaServiceName;\n operation?: string;\n result?: string;\n resultLevel?: ArcaFiscalResultLevel;\n results?: ArcaFiscalResults;\n cae?: string;\n issues?: readonly ArcaFiscalIssue[];\n }\n ) {\n super(message, \"ARCA_SERVICE_ERROR\", options);\n this.serviceCode = options?.serviceCode;\n this.service = options?.service;\n this.operation = options?.operation;\n this.result = options?.result;\n this.resultLevel = options?.resultLevel;\n this.results = options?.results;\n this.cae = options?.cae;\n this.issues = options?.issues;\n }\n}\n\nfunction normalizeProviderCode(\n providerCode: string | number | undefined\n): string | number | undefined {\n if (typeof providerCode === \"number\") {\n return Number.isFinite(providerCode) ? providerCode : undefined;\n }\n if (typeof providerCode === \"string\") {\n return redactDiagnosticPreview(providerCode, 512);\n }\n return undefined;\n}\n"],"mappings":";AAAO,IAAM,gCAAgC;AAE7C,IAAM,+BAA+B;AACrC,IAAM,6BAA6B;AACnC,IAAM,+BAA+B,IAAI;AAAA,EACvC,IAAI,0BAA0B;AAAA,EAC9B;AACF;AACA,IAAM,qCAAqC,IAAI;AAAA,EAC7C,IAAI,0BAA0B;AAAA,EAC9B;AACF;AACA,IAAM,qCAAqC,IAAI;AAAA,EAC7C,IAAI,0BAA0B;AAAA,EAC9B;AACF;AAkBO,SAAS,wBACd,OACA,qBAAqB,+BACb;AACR,QAAM,YAAY,uBAAuB,kBAAkB;AAE3D,SAAO,MACJ;AAAA,IACC;AAAA,IACA,CAAC,QAAQ,YAAoB,IAAI,OAAO,gBAAgB,OAAO;AAAA,EACjE,EACC;AAAA,IACC;AAAA,IACA,CAAC,QAAQ,YAAoB,IAAI,OAAO,gBAAgB,OAAO;AAAA,EACjE,EACC;AAAA,IACC;AAAA,IACA,CAAC,QAAQ,YAAoB,IAAI,OAAO;AAAA,EAC1C,EACC,MAAM,GAAG,SAAS;AACvB;AAGO,SAAS,6BACd,cACA,qBAAqB,+BACG;AACxB,SAAO;AAAA,IACL,oBAAoB,aAAa;AAAA,IACjC,qBAAqB;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAGO,SAAS,0BAA0B,OAAqC;AAC7E,MAAI,EAAE,SAAS,OAAO,UAAU,WAAW;AACzC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAY;AAClB,QAAM,aAAkC,CAAC;AAEzC,mBAAiB,YAAY,aAAa,UAAU,IAAI;AACxD,mBAAiB,YAAY,aAAa,UAAU,IAAI;AACxD,mBAAiB,YAAY,cAAc,UAAU,UAAU;AAC/D,mBAAiB,YAAY,eAAe,UAAU,WAAW;AACjE;AAAA,IACE;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ;AACA,MAAI,OAAO,UAAU,wBAAwB,UAAU;AACrD,eAAW,sBAAsB;AAAA,MAC/B,UAAU;AAAA,IACZ;AAAA,EACF;AACA,mBAAiB,YAAY,aAAa,UAAU,SAAS;AAE7D,SAAO;AACT;AAEA,SAAS,uBAAuB,oBAAoC;AAClE,MAAI,CAAC,OAAO,SAAS,kBAAkB,GAAG;AACxC,WAAO;AAAA,EACT;AAEA,SAAO,KAAK;AAAA,IACV;AAAA,IACA,KAAK,IAAI,KAAK,MAAM,kBAAkB,GAAG,6BAA6B;AAAA,EACxE;AACF;AAEA,SAAS,iBAEP,QAA6B,KAAW,OAAsB;AAC9D,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,GAAG,IAAI,wBAAwB,OAAO,4BAA4B;AAAA,EAC3E;AACF;AAEA,SAAS,iBACP,QACA,KACA,OACM;AACN,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO,GAAG,IAAI;AAAA,EAChB;AACF;;;ACnHO,IAAM,YAAN,cAAwB,MAAM;AAAA,EAC1B;AAAA,EACS,OAAe;AAAA,EAEjC,YAAY,SAAiB,OAAO,cAAc,SAAwB;AACxE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,yBAAN,cAAqC,UAAU;AAAA,EAClC,OAAe;AAAA,EAEjC,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,4BAA4B,OAAO;AAAA,EACpD;AACF;AAoBO,IAAM,iBAAN,cAA6B,UAAU;AAAA,EAE1B,OAAe;AAAA,EACxB;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAAgC;AAC3D,UAAM,SAAS,QAAQ,MAAM,OAAO;AACpC,SAAK,QAAQ,QAAQ;AACrB,SAAK,WAAW,QAAQ;AAAA,EAC1B;AACF;AAiBO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EAEnC,OAAe;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAAyC;AACpE;AAAA,MACE,wBAAwB,OAAO;AAAA,MAC/B;AAAA,MACA;AAAA,IACF;AACA,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ;AACvB,SAAK,YAAY,QAAQ;AACzB,SAAK,eAAe,sBAAsB,QAAQ,YAAY;AAAA,EAChE;AACF;AAGO,SAAS,0BACd,OACkC;AAClC,SAAO,iBAAiB;AAC1B;AAGO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAC9B,OAAe;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,SACA,SAMA;AACA,UAAM,SAAS,wBAAwB,OAAO;AAC9C,SAAK,aAAa,SAAS;AAC3B,SAAK,cAAc,SAAS;AAC5B,SAAK,qBAAqB,SAAS;AACnC,SAAK,sBACH,SAAS,wBAAwB,SAC7B,SACA,wBAAwB,QAAQ,mBAAmB;AAAA,EAC3D;AACF;AAGO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAC9B,OAAe;AAAA,EACxB;AAAA,EAET,YACE,SACA,SAGA;AACA,UAAM,wBAAwB,OAAO,GAAG,mBAAmB,OAAO;AAClE,SAAK,YACH,SAAS,cAAc,SACnB,SACA,wBAAwB,QAAQ,SAAS;AAAA,EACjD;AACF;AAGO,IAAM,+BAAN,cAA2C,UAAU;AAAA,EACxC,OAAe;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,SACA,SASA;AACA,UAAM,SAAS,8BAA8B,OAAO;AACpD,SAAK,UAAU,SAAS;AACxB,SAAK,YAAY,SAAS;AAC1B,SAAK,cAAc,SAAS;AAC5B,SAAK,aAAa,SAAS;AAC3B,SAAK,cAAc,SAAS;AAC5B,SAAK,qBAAqB,SAAS;AACnC,SAAK,sBACH,SAAS,wBAAwB,SAC7B,SACA,wBAAwB,QAAQ,mBAAmB;AAAA,EAC3D;AACF;AAGO,IAAM,mBAAN,cAA+B,UAAU;AAAA,EAC5B,OAAe;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,SACA,SAUA;AACA,UAAM,SAAS,sBAAsB,OAAO;AAC5C,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,SAAS;AACxB,SAAK,YAAY,SAAS;AAC1B,SAAK,SAAS,SAAS;AACvB,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,SAAS;AACxB,SAAK,MAAM,SAAS;AACpB,SAAK,SAAS,SAAS;AAAA,EACzB;AACF;AAEA,SAAS,sBACP,cAC6B;AAC7B,MAAI,OAAO,iBAAiB,UAAU;AACpC,WAAO,OAAO,SAAS,YAAY,IAAI,eAAe;AAAA,EACxD;AACA,MAAI,OAAO,iBAAiB,UAAU;AACpC,WAAO,wBAAwB,cAAc,GAAG;AAAA,EAClD;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/internal/redaction.ts","../src/errors.ts"],"sourcesContent":["export const MAX_DIAGNOSTIC_PREVIEW_LENGTH = 4096;\n\nconst MAX_DIAGNOSTIC_SCALAR_LENGTH = 512;\nconst SENSITIVE_XML_ELEMENT_NAME = \"((?:[A-Za-z_][\\\\w.-]*:)?(?:Token|Sign))\";\nconst PAIRED_SENSITIVE_XML_ELEMENT = new RegExp(\n `<${SENSITIVE_XML_ELEMENT_NAME}\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\/\\\\1\\\\s*>`,\n \"gi\"\n);\nconst SELF_CLOSING_SENSITIVE_XML_ELEMENT = new RegExp(\n `<${SENSITIVE_XML_ELEMENT_NAME}\\\\b[^>]*\\\\/\\\\s*>`,\n \"gi\"\n);\nconst UNTERMINATED_SENSITIVE_XML_ELEMENT = new RegExp(\n `<${SENSITIVE_XML_ELEMENT_NAME}\\\\b[^>]*>[^<]*`,\n \"gi\"\n);\n\nexport type ResponseBodyDiagnostic = {\n responseBodyLength: number;\n responseBodyPreview: string;\n};\n\nexport type SafeErrorDiagnostic = {\n errorName?: string;\n errorCode?: string;\n statusCode?: number;\n contentType?: string;\n responseBodyLength?: number;\n responseBodyPreview?: string;\n faultCode?: string;\n};\n\n/** Redacts credential-bearing XML elements and applies the global preview bound. */\nexport function redactDiagnosticPreview(\n value: string,\n requestedMaxLength = MAX_DIAGNOSTIC_PREVIEW_LENGTH\n): string {\n const maxLength = normalizePreviewLength(requestedMaxLength);\n\n return value\n .replace(\n PAIRED_SENSITIVE_XML_ELEMENT,\n (_match, tagName: string) => `<${tagName}>[REDACTED]</${tagName}>`\n )\n .replace(\n SELF_CLOSING_SENSITIVE_XML_ELEMENT,\n (_match, tagName: string) => `<${tagName}>[REDACTED]</${tagName}>`\n )\n .replace(\n UNTERMINATED_SENSITIVE_XML_ELEMENT,\n (_match, tagName: string) => `<${tagName}>[REDACTED]`\n )\n .slice(0, maxLength);\n}\n\n/** Produces the only response-body shape allowed in errors and logs. */\nexport function createResponseBodyDiagnostic(\n responseBody: string,\n requestedMaxLength = MAX_DIAGNOSTIC_PREVIEW_LENGTH\n): ResponseBodyDiagnostic {\n return {\n responseBodyLength: responseBody.length,\n responseBodyPreview: redactDiagnosticPreview(\n responseBody,\n requestedMaxLength\n ),\n };\n}\n\n/** Extracts a scalar allowlist from an error without exposing the error or cause. */\nexport function createSafeErrorDiagnostic(error: unknown): SafeErrorDiagnostic {\n if (!(error && typeof error === \"object\")) {\n return {};\n }\n\n const candidate = error as Record<string, unknown>;\n const diagnostic: SafeErrorDiagnostic = {};\n\n assignSafeString(diagnostic, \"errorName\", candidate.name);\n assignSafeString(diagnostic, \"errorCode\", candidate.code);\n assignSafeNumber(diagnostic, \"statusCode\", candidate.statusCode);\n assignSafeString(diagnostic, \"contentType\", candidate.contentType);\n assignSafeNumber(\n diagnostic,\n \"responseBodyLength\",\n candidate.responseBodyLength\n );\n if (typeof candidate.responseBodyPreview === \"string\") {\n diagnostic.responseBodyPreview = redactDiagnosticPreview(\n candidate.responseBodyPreview\n );\n }\n assignSafeString(diagnostic, \"faultCode\", candidate.faultCode);\n\n return diagnostic;\n}\n\nfunction normalizePreviewLength(requestedMaxLength: number): number {\n if (!Number.isFinite(requestedMaxLength)) {\n return MAX_DIAGNOSTIC_PREVIEW_LENGTH;\n }\n\n return Math.max(\n 0,\n Math.min(Math.trunc(requestedMaxLength), MAX_DIAGNOSTIC_PREVIEW_LENGTH)\n );\n}\n\nfunction assignSafeString<\n TKey extends \"errorName\" | \"errorCode\" | \"contentType\" | \"faultCode\",\n>(target: SafeErrorDiagnostic, key: TKey, value: unknown): void {\n if (typeof value === \"string\") {\n target[key] = redactDiagnosticPreview(value, MAX_DIAGNOSTIC_SCALAR_LENGTH);\n }\n}\n\nfunction assignSafeNumber<TKey extends \"statusCode\" | \"responseBodyLength\">(\n target: SafeErrorDiagnostic,\n key: TKey,\n value: unknown\n): void {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n target[key] = value;\n }\n}\n","import { redactDiagnosticPreview } from \"./internal/redaction\";\nimport type { ArcaServiceName } from \"./internal/types\";\nimport type {\n ArcaFiscalIssue,\n ArcaFiscalResultLevel,\n ArcaFiscalResults,\n} from \"./services/fiscal-evidence\";\n\n/** Base error class for all ARCA-related errors. */\nexport class ArcaError extends Error {\n readonly code: string;\n override readonly name: string = \"ArcaError\";\n\n constructor(message: string, code = \"ARCA_ERROR\", options?: ErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** Thrown when the ARCA client configuration is missing or invalid. */\nexport class ArcaConfigurationError extends ArcaError {\n override readonly name: string = \"ArcaConfigurationError\";\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, \"ARCA_CONFIGURATION_ERROR\", options);\n }\n}\n\n/** Stable routing codes for caller-provided input failures. */\nexport type ArcaInputErrorCode =\n | \"ARCA_INPUT_INVALID_DATE\"\n | \"ARCA_INPUT_INVALID_AMOUNT\"\n | \"ARCA_INPUT_AMOUNT_PRECISION\"\n | \"ARCA_INPUT_AMOUNT_MISMATCH\"\n | \"ARCA_INPUT_INVALID_EXCHANGE_RATE\"\n | \"ARCA_INPUT_INVALID_VALUE\"\n | \"ARCA_INPUT_MISSING_FIELD\"\n | \"ARCA_INPUT_RESERVED_FIELD\";\n\nexport type ArcaInputErrorOptions = ErrorOptions & {\n code: ArcaInputErrorCode;\n field?: string;\n expected?: string;\n};\n\n/** Thrown when caller-provided input data is missing or invalid. */\nexport class ArcaInputError extends ArcaError {\n declare readonly code: ArcaInputErrorCode;\n override readonly name: string = \"ArcaInputError\";\n readonly field?: string;\n readonly expected?: string;\n\n constructor(message: string, options: ArcaInputErrorOptions) {\n super(message, options.code, options);\n this.field = options.field;\n this.expected = options.expected;\n }\n}\n\n/** Stable reasons exposed for explicit ARCA authentication rejections. */\nexport type ArcaAuthenticationReason =\n | \"invalid_token\"\n | \"unauthorized_computer\"\n | \"missing_relationship\"\n | \"authentication_rejected\";\n\nexport type ArcaAuthenticationErrorOptions = ErrorOptions & {\n reason: ArcaAuthenticationReason;\n service: ArcaServiceName;\n operation: string;\n providerCode?: string | number;\n};\n\n/** Thrown when ARCA explicitly rejects credentials before an operation runs. */\nexport class ArcaAuthenticationError extends ArcaError {\n declare readonly code: \"ARCA_AUTHENTICATION_ERROR\";\n override readonly name: string = \"ArcaAuthenticationError\";\n readonly reason: ArcaAuthenticationReason;\n readonly service: ArcaServiceName;\n readonly operation: string;\n readonly providerCode?: string | number;\n\n constructor(message: string, options: ArcaAuthenticationErrorOptions) {\n super(\n redactDiagnosticPreview(message),\n \"ARCA_AUTHENTICATION_ERROR\",\n options\n );\n this.reason = options.reason;\n this.service = options.service;\n this.operation = options.operation;\n this.providerCode = normalizeProviderCode(options.providerCode);\n }\n}\n\n/** Narrows unknown failures to the explicit authentication error contract. */\nexport function isArcaAuthenticationError(\n error: unknown\n): error is ArcaAuthenticationError {\n return error instanceof ArcaAuthenticationError;\n}\n\n/** Thrown when an HTTP request to an ARCA endpoint fails at the transport level. */\nexport class ArcaTransportError extends ArcaError {\n override readonly name: string = \"ArcaTransportError\";\n readonly statusCode?: number;\n readonly contentType?: string;\n readonly responseBodyLength?: number;\n readonly responseBodyPreview?: string;\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n statusCode?: number;\n contentType?: string;\n responseBodyLength?: number;\n responseBodyPreview?: string;\n }\n ) {\n super(message, \"ARCA_TRANSPORT_ERROR\", options);\n this.statusCode = options?.statusCode;\n this.contentType = options?.contentType;\n this.responseBodyLength = options?.responseBodyLength;\n this.responseBodyPreview =\n options?.responseBodyPreview === undefined\n ? undefined\n : redactDiagnosticPreview(options.responseBodyPreview);\n }\n}\n\n/** Thrown when the SOAP response contains a Fault element. */\nexport class ArcaSoapFaultError extends ArcaError {\n override readonly name: string = \"ArcaSoapFaultError\";\n readonly faultCode?: string;\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n faultCode?: string;\n }\n ) {\n super(redactDiagnosticPreview(message), \"ARCA_SOAP_FAULT\", options);\n this.faultCode =\n options?.faultCode === undefined\n ? undefined\n : redactDiagnosticPreview(options.faultCode);\n }\n}\n\n/** Thrown when a response cannot be parsed as a valid SOAP envelope. */\nexport class ArcaInvalidSoapResponseError extends ArcaError {\n override readonly name: string = \"ArcaInvalidSoapResponseError\";\n readonly service?: ArcaServiceName;\n readonly operation?: string;\n readonly endpointUrl?: string;\n readonly statusCode?: number;\n readonly contentType?: string;\n readonly responseBodyLength?: number;\n readonly responseBodyPreview?: string;\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n service?: ArcaServiceName;\n operation?: string;\n endpointUrl?: string;\n statusCode?: number;\n contentType?: string;\n responseBodyLength?: number;\n responseBodyPreview?: string;\n }\n ) {\n super(message, \"ARCA_INVALID_SOAP_RESPONSE\", options);\n this.service = options?.service;\n this.operation = options?.operation;\n this.endpointUrl = options?.endpointUrl;\n this.statusCode = options?.statusCode;\n this.contentType = options?.contentType;\n this.responseBodyLength = options?.responseBodyLength;\n this.responseBodyPreview =\n options?.responseBodyPreview === undefined\n ? undefined\n : redactDiagnosticPreview(options.responseBodyPreview);\n }\n}\n\n/** Thrown when an ARCA service (WSFE, WSMTXCA, Padron) returns a domain-level error. */\nexport class ArcaServiceError extends ArcaError {\n override readonly name: string = \"ArcaServiceError\";\n readonly serviceCode?: string | number;\n readonly service?: ArcaServiceName;\n readonly operation?: string;\n readonly result?: string;\n readonly resultLevel?: ArcaFiscalResultLevel;\n readonly results?: ArcaFiscalResults;\n readonly cae?: string;\n readonly issues?: readonly ArcaFiscalIssue[];\n\n constructor(\n message: string,\n options?: ErrorOptions & {\n serviceCode?: string | number;\n service?: ArcaServiceName;\n operation?: string;\n result?: string;\n resultLevel?: ArcaFiscalResultLevel;\n results?: ArcaFiscalResults;\n cae?: string;\n issues?: readonly ArcaFiscalIssue[];\n }\n ) {\n super(message, \"ARCA_SERVICE_ERROR\", options);\n this.serviceCode = options?.serviceCode;\n this.service = options?.service;\n this.operation = options?.operation;\n this.result = options?.result;\n this.resultLevel = options?.resultLevel;\n this.results = options?.results;\n this.cae = options?.cae;\n this.issues = options?.issues;\n }\n}\n\nfunction normalizeProviderCode(\n providerCode: string | number | undefined\n): string | number | undefined {\n if (typeof providerCode === \"number\") {\n return Number.isFinite(providerCode) ? providerCode : undefined;\n }\n if (typeof providerCode === \"string\") {\n return redactDiagnosticPreview(providerCode, 512);\n }\n return undefined;\n}\n\n/** Narrow error evidence: never includes a cause, raw response or stack. */\nexport type ArcaSafeErrorMetadata = {\n name: string;\n message: string;\n code?: string;\n statusCode?: number;\n};\n\nexport function toArcaSafeErrorMetadata(error: unknown): ArcaSafeErrorMetadata {\n if (!(error instanceof Error)) {\n return { name: \"UnknownError\", message: String(error) };\n }\n return {\n name: error.name,\n message: error.message,\n ...(error instanceof ArcaError ? { code: error.code } : {}),\n ...(error instanceof ArcaTransportError && error.statusCode !== undefined\n ? { statusCode: error.statusCode }\n : {}),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ArcaSoapFaultError
3
- } from "./chunk-MBWOFO67.mjs";
3
+ } from "./chunk-HUT3PFKF.mjs";
4
4
 
5
5
  // src/services/padron.ts
6
6
  function createPadronService(options) {
@@ -103,4 +103,4 @@ async function executePadronOperation(options, service, operation, body) {
103
103
  export {
104
104
  createPadronService
105
105
  };
106
- //# sourceMappingURL=chunk-EDY3PNKJ.mjs.map
106
+ //# sourceMappingURL=chunk-NUV5RZPZ.mjs.map
@@ -3,7 +3,7 @@ import {
3
3
  ArcaServiceError,
4
4
  ArcaSoapFaultError,
5
5
  isArcaAuthenticationError
6
- } from "./chunk-MBWOFO67.mjs";
6
+ } from "./chunk-HUT3PFKF.mjs";
7
7
 
8
8
  // src/internal/authentication.ts
9
9
  var WSFE_AUTHENTICATION_CODES = {
@@ -192,4 +192,4 @@ export {
192
192
  createArcaAuthenticationErrorFromEvidence,
193
193
  executeWithAuthenticationRecovery
194
194
  };
195
- //# sourceMappingURL=chunk-IOKZX6CA.mjs.map
195
+ //# sourceMappingURL=chunk-PPYGVNFA.mjs.map
@@ -2,21 +2,21 @@ import {
2
2
  ARCA_CURRENCY_IDS,
3
3
  ARCA_VAT_RATES,
4
4
  ARCA_VOUCHER_TYPES
5
- } from "./chunk-VVY2LZIZ.mjs";
5
+ } from "./chunk-76WU5BVI.mjs";
6
6
  import {
7
7
  classifyArcaAuthenticationError,
8
8
  classifyArcaAuthenticationIssues,
9
9
  createArcaAuthenticationErrorFromEvidence,
10
10
  createArcaAuthenticationEvidence,
11
11
  executeWithAuthenticationRecovery
12
- } from "./chunk-IOKZX6CA.mjs";
12
+ } from "./chunk-PPYGVNFA.mjs";
13
13
  import {
14
14
  ArcaInputError,
15
15
  ArcaInvalidSoapResponseError,
16
16
  ArcaServiceError,
17
17
  ArcaSoapFaultError,
18
18
  ArcaTransportError
19
- } from "./chunk-MBWOFO67.mjs";
19
+ } from "./chunk-HUT3PFKF.mjs";
20
20
 
21
21
  // src/internal/decimal.ts
22
22
  var AMOUNT_SCALE = 100;
@@ -1110,8 +1110,72 @@ function mapWsfeVoucherInfo(raw) {
1110
1110
  "caeExpiry",
1111
1111
  normalizeWsfeString(raw.FchVto ?? raw.CAEFchVto)
1112
1112
  );
1113
+ assignWsfeValue(
1114
+ voucher,
1115
+ "serviceStartDate",
1116
+ normalizeWsfeString(raw.FchServDesde)
1117
+ );
1118
+ assignWsfeValue(
1119
+ voucher,
1120
+ "serviceEndDate",
1121
+ normalizeWsfeString(raw.FchServHasta)
1122
+ );
1123
+ assignWsfeValue(
1124
+ voucher,
1125
+ "paymentDueDate",
1126
+ normalizeWsfeString(raw.FchVtoPago)
1127
+ );
1128
+ assignWsfeValue(
1129
+ voucher,
1130
+ "vatRates",
1131
+ mapWsfeLookupDetails(raw.Iva, "AlicIva", mapWsfeLookupVat)
1132
+ );
1133
+ assignWsfeValue(
1134
+ voucher,
1135
+ "taxes",
1136
+ mapWsfeLookupDetails(raw.Tributos, "Tributo", mapWsfeLookupTax)
1137
+ );
1113
1138
  return voucher;
1114
1139
  }
1140
+ function mapWsfeLookupDetails(container, key, map) {
1141
+ const record = toWsfeRecord(container);
1142
+ if (!record || record[key] === void 0) {
1143
+ return void 0;
1144
+ }
1145
+ const rows = Array.isArray(record[key]) ? record[key] : [record[key]];
1146
+ const result = [];
1147
+ for (const value of rows) {
1148
+ const row = toWsfeRecord(value);
1149
+ const mapped = row ? map(row) : void 0;
1150
+ if (mapped === void 0) {
1151
+ return void 0;
1152
+ }
1153
+ result.push(mapped);
1154
+ }
1155
+ return result;
1156
+ }
1157
+ function mapWsfeLookupVat(row) {
1158
+ const id = normalizeWsfeNumber(row.Id);
1159
+ const baseAmount = normalizeWsfeNumber(row.BaseImp);
1160
+ const amount = normalizeWsfeNumber(row.Importe);
1161
+ if (id === void 0 || baseAmount === void 0 || amount === void 0) {
1162
+ return void 0;
1163
+ }
1164
+ return { id, baseAmount, amount };
1165
+ }
1166
+ function mapWsfeLookupTax(row) {
1167
+ const vat = mapWsfeLookupVat(row);
1168
+ const rate = normalizeWsfeNumber(row.Alic);
1169
+ if (!vat || rate === void 0) {
1170
+ return void 0;
1171
+ }
1172
+ const description = normalizeWsfeString(row.Desc);
1173
+ return {
1174
+ ...vat,
1175
+ rate,
1176
+ ...description === void 0 ? {} : { description }
1177
+ };
1178
+ }
1115
1179
  function createWsfeAuth(representedTaxId, token, sign) {
1116
1180
  return {
1117
1181
  Token: token,
@@ -1418,15 +1482,141 @@ function getWsfeResultEntries(result, key) {
1418
1482
  );
1419
1483
  }
1420
1484
 
1421
- // src/services/wsfe-builders.ts
1422
- var VAT_RATE_IDS = {
1423
- 0: ARCA_VAT_RATES.IVA_0,
1424
- 2.5: ARCA_VAT_RATES.IVA_2_5,
1425
- 5: ARCA_VAT_RATES.IVA_5,
1426
- 10.5: ARCA_VAT_RATES.IVA_10_5,
1427
- 21: ARCA_VAT_RATES.IVA_21,
1428
- 27: ARCA_VAT_RATES.IVA_27
1485
+ // src/services/wsfe-amounts.ts
1486
+ var RATES = {
1487
+ 0: { id: ARCA_VAT_RATES.IVA_0, basisPoints: 0n },
1488
+ 2.5: { id: ARCA_VAT_RATES.IVA_2_5, basisPoints: 250n },
1489
+ 5: { id: ARCA_VAT_RATES.IVA_5, basisPoints: 500n },
1490
+ 10.5: { id: ARCA_VAT_RATES.IVA_10_5, basisPoints: 1050n },
1491
+ 21: { id: ARCA_VAT_RATES.IVA_21, basisPoints: 2100n },
1492
+ 27: { id: ARCA_VAT_RATES.IVA_27, basisPoints: 2700n }
1429
1493
  };
1494
+ function calculateWsfeAmounts(input) {
1495
+ if (!Array.isArray(input.items) || input.items.length === 0) {
1496
+ invalidItem("items", "a non-empty array of items");
1497
+ }
1498
+ const isVat = input.issuer === "responsable_inscripto";
1499
+ if (!(isVat || ["monotributo", "exento", "no_alcanzado"].includes(input.issuer))) {
1500
+ invalidItem("issuer", "a supported issuer condition");
1501
+ }
1502
+ const totals = collectItems(input.items, isVat);
1503
+ let net = totals.net;
1504
+ let vat = 0n;
1505
+ const { exempt, untaxed, groups } = totals;
1506
+ const vatRates = [];
1507
+ for (const [rate, group] of groups) {
1508
+ const { id, basisPoints } = RATES[rate];
1509
+ const netFromGross = roundHalfEvenRatio(
1510
+ group.gross * 10000n,
1511
+ 10000n + basisPoints
1512
+ );
1513
+ const base = group.net + netFromGross;
1514
+ const tax = roundHalfEvenRatio(group.net * basisPoints, 10000n) + group.gross - netFromGross;
1515
+ if (base === 0n) {
1516
+ continue;
1517
+ }
1518
+ net += base;
1519
+ vat += tax;
1520
+ vatRates.push({
1521
+ id,
1522
+ baseAmount: arcaMinorUnitsToNumber(base, "netAmount"),
1523
+ amount: arcaMinorUnitsToNumber(tax, "vatAmount")
1524
+ });
1525
+ }
1526
+ const computed = net + vat + exempt + untaxed;
1527
+ arcaMinorUnitsToNumber(computed, "totalAmount");
1528
+ const sent = input.total === void 0 ? computed : assertArcaMinorUnits(input.total, "total");
1529
+ const adjustment = sent - computed;
1530
+ const allowance = BigInt(vatRates.length);
1531
+ if (adjustment < -allowance || adjustment > allowance || vat + adjustment < 0n) {
1532
+ throw new ArcaInputError(
1533
+ "total does not match the computed amount within the VAT allowance.",
1534
+ {
1535
+ code: "ARCA_INPUT_AMOUNT_MISMATCH",
1536
+ field: "total",
1537
+ expected: `${computed} minor units (at most ${allowance} minor units of VAT adjustment, with non-negative VAT)`
1538
+ }
1539
+ );
1540
+ }
1541
+ return {
1542
+ data: {
1543
+ totalAmount: arcaMinorUnitsToNumber(sent, "totalAmount"),
1544
+ netAmount: arcaMinorUnitsToNumber(net, "netAmount"),
1545
+ vatAmount: arcaMinorUnitsToNumber(vat + adjustment, "vatAmount"),
1546
+ nonTaxableAmount: arcaMinorUnitsToNumber(untaxed, "nonTaxableAmount"),
1547
+ exemptAmount: arcaMinorUnitsToNumber(exempt, "exemptAmount"),
1548
+ taxAmount: 0,
1549
+ ...isVat ? { vatRates } : {}
1550
+ },
1551
+ amounts: {
1552
+ computedTotal: Number(computed),
1553
+ sentTotal: Number(sent),
1554
+ vatAdjustment: Number(adjustment)
1555
+ }
1556
+ };
1557
+ }
1558
+ function collectItems(items, isVat) {
1559
+ let net = 0n;
1560
+ let exempt = 0n;
1561
+ let untaxed = 0n;
1562
+ const groups = /* @__PURE__ */ new Map();
1563
+ for (const [index, item] of items.entries()) {
1564
+ const path = `items[${index}]`;
1565
+ if (item === null || typeof item !== "object" || Array.isArray(item)) {
1566
+ invalidItem(path, "an item object");
1567
+ }
1568
+ if (!isVat) {
1569
+ net += classCAmount(item, path);
1570
+ continue;
1571
+ }
1572
+ const { amount, field, rate } = vatItemAmount(item, path);
1573
+ if (rate === "exempt") {
1574
+ exempt += amount;
1575
+ continue;
1576
+ }
1577
+ if (rate === "untaxed") {
1578
+ untaxed += amount;
1579
+ continue;
1580
+ }
1581
+ const group = groups.get(rate) ?? { net: 0n, gross: 0n };
1582
+ group[field] += amount;
1583
+ groups.set(rate, group);
1584
+ }
1585
+ return { net, exempt, untaxed, groups };
1586
+ }
1587
+ function classCAmount(item, path) {
1588
+ if ("vat" in item || "net" in item || "gross" in item) {
1589
+ invalidItem("items", "amount items for a non-RI issuer");
1590
+ }
1591
+ return assertArcaMinorUnits(item.amount, `${path}.amount`);
1592
+ }
1593
+ function vatItemAmount(item, path) {
1594
+ if ("amount" in item || "net" in item === "gross" in item) {
1595
+ invalidItem(
1596
+ "items",
1597
+ "exactly one of net or gross, and vat, for an RI issuer"
1598
+ );
1599
+ }
1600
+ const field = "net" in item ? "net" : "gross";
1601
+ const amount = assertArcaMinorUnits(
1602
+ item[field],
1603
+ `${path}.${field}`
1604
+ );
1605
+ const rate = item.vat;
1606
+ if (rate !== "exempt" && rate !== "untaxed" && (typeof rate !== "number" || !Object.hasOwn(RATES, rate))) {
1607
+ invalidItem(`${path}.vat`, "0, 2.5, 5, 10.5, 21, 27, exempt, or untaxed");
1608
+ }
1609
+ return { amount, field, rate };
1610
+ }
1611
+ function invalidItem(field, expected) {
1612
+ throw new ArcaInputError(`${field} must be ${expected}.`, {
1613
+ code: "ARCA_INPUT_INVALID_VALUE",
1614
+ field,
1615
+ expected
1616
+ });
1617
+ }
1618
+
1619
+ // src/services/wsfe-builders.ts
1430
1620
  function buildFacturaB(input) {
1431
1621
  const taxableMinorUnits = assertArcaMinorUnits(
1432
1622
  input.taxableAmount,
@@ -1447,15 +1637,6 @@ function buildFacturaB(input) {
1447
1637
  input.vatRate,
1448
1638
  "vatRate"
1449
1639
  );
1450
- const totalMinorUnits = taxableMinorUnits + vatMinorUnits;
1451
- const vatRateId = VAT_RATE_IDS[input.vatRate];
1452
- if (vatRateId === void 0) {
1453
- throw new ArcaInputError("vatRate is not a supported VAT rate.", {
1454
- code: "ARCA_INPUT_INVALID_VALUE",
1455
- field: "vatRate",
1456
- expected: "one of 0, 2.5, 5, 10.5, 21, or 27"
1457
- });
1458
- }
1459
1640
  if (input.vatRate !== 0 && vatMinorUnits === 0n) {
1460
1641
  throw new ArcaInputError(
1461
1642
  "taxableAmount is too small to produce VAT at the selected positive vatRate.",
@@ -1466,39 +1647,30 @@ function buildFacturaB(input) {
1466
1647
  }
1467
1648
  );
1468
1649
  }
1469
- const vatRates = [
1470
- Object.freeze({
1471
- id: vatRateId,
1472
- baseAmount: arcaMinorUnitsToNumber(taxableMinorUnits, "taxableAmount"),
1473
- amount: arcaMinorUnitsToNumber(vatMinorUnits, "vatAmount")
1474
- })
1475
- ];
1476
- Object.freeze(vatRates);
1650
+ const { data } = calculateWsfeAmounts({
1651
+ issuer: "responsable_inscripto",
1652
+ items: [{ net: input.taxableAmount, vat: input.vatRate }]
1653
+ });
1654
+ for (const rate of data.vatRates ?? []) {
1655
+ Object.freeze(rate);
1656
+ }
1657
+ Object.freeze(data.vatRates);
1477
1658
  return Object.freeze({
1478
1659
  ...buildCommonExactInput(input),
1479
1660
  voucherType: ARCA_VOUCHER_TYPES.FACTURA_B,
1480
- totalAmount: arcaMinorUnitsToNumber(totalMinorUnits, "totalAmount"),
1481
- nonTaxableAmount: 0,
1482
- netAmount: arcaMinorUnitsToNumber(taxableMinorUnits, "taxableAmount"),
1483
- exemptAmount: 0,
1484
- taxAmount: 0,
1485
- vatAmount: arcaMinorUnitsToNumber(vatMinorUnits, "vatAmount"),
1486
- vatRates
1661
+ ...data
1487
1662
  });
1488
1663
  }
1489
1664
  function buildFacturaC(input) {
1490
- const amountMinorUnits = assertArcaMinorUnits(input.amount, "amount");
1491
- const amount = arcaMinorUnitsToNumber(amountMinorUnits, "amount");
1665
+ assertArcaMinorUnits(input.amount, "amount");
1666
+ const { data } = calculateWsfeAmounts({
1667
+ issuer: "monotributo",
1668
+ items: [{ amount: input.amount }]
1669
+ });
1492
1670
  return Object.freeze({
1493
1671
  ...buildCommonExactInput(input),
1494
1672
  voucherType: ARCA_VOUCHER_TYPES.FACTURA_C,
1495
- totalAmount: amount,
1496
- nonTaxableAmount: 0,
1497
- // ARCA defines ImpNeto as the subtotal for class C vouchers.
1498
- netAmount: amount,
1499
- exemptAmount: 0,
1500
- taxAmount: 0,
1501
- vatAmount: 0
1673
+ ...data
1502
1674
  });
1503
1675
  }
1504
1676
  function buildCommonExactInput(input) {
@@ -1595,8 +1767,13 @@ function normalizeBuilderCurrency(input) {
1595
1767
  }
1596
1768
 
1597
1769
  export {
1770
+ normalizeArcaAmountToMinorUnits,
1771
+ serializeArcaExchangeRate,
1598
1772
  createWsfeService,
1773
+ normalizeWsfeVoucherInput,
1774
+ normalizeWsfeDateInput,
1775
+ calculateWsfeAmounts,
1599
1776
  buildFacturaB,
1600
1777
  buildFacturaC
1601
1778
  };
1602
- //# sourceMappingURL=chunk-OHHXHYLV.mjs.map
1779
+ //# sourceMappingURL=chunk-TOVSOJ3G.mjs.map