facturas 0.7.0 → 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/dist/index.mjs CHANGED
@@ -1,16 +1,29 @@
1
1
  import {
2
2
  createPadronService
3
- } from "./chunk-EDY3PNKJ.mjs";
3
+ } from "./chunk-NUV5RZPZ.mjs";
4
4
  import {
5
5
  buildFacturaB,
6
6
  buildFacturaC,
7
- createWsfeService
8
- } from "./chunk-C55KOV5N.mjs";
9
- import "./chunk-VVY2LZIZ.mjs";
7
+ calculateWsfeAmounts,
8
+ createWsfeService,
9
+ normalizeArcaAmountToMinorUnits,
10
+ normalizeWsfeDateInput,
11
+ normalizeWsfeVoucherInput,
12
+ serializeArcaExchangeRate
13
+ } from "./chunk-TOVSOJ3G.mjs";
14
+ import {
15
+ ARCA_CURRENCY_IDS,
16
+ ARCA_DOCUMENT_TYPES,
17
+ ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS,
18
+ ARCA_INVOICE_CLASS_BY_ISSUER,
19
+ ARCA_ISSUER_CONDITION_IDS,
20
+ ARCA_RECEIVER_CONDITION_IDS,
21
+ ARCA_VOUCHER_TYPES
22
+ } from "./chunk-76WU5BVI.mjs";
10
23
  import {
11
24
  createWsmtxcaService
12
- } from "./chunk-PKE4Z4GE.mjs";
13
- import "./chunk-IOKZX6CA.mjs";
25
+ } from "./chunk-ZX4OOCML.mjs";
26
+ import "./chunk-PPYGVNFA.mjs";
14
27
  import {
15
28
  ArcaAuthenticationError,
16
29
  ArcaConfigurationError,
@@ -22,8 +35,9 @@ import {
22
35
  ArcaTransportError,
23
36
  createResponseBodyDiagnostic,
24
37
  createSafeErrorDiagnostic,
25
- isArcaAuthenticationError
26
- } from "./chunk-MBWOFO67.mjs";
38
+ isArcaAuthenticationError,
39
+ toArcaSafeErrorMetadata
40
+ } from "./chunk-HUT3PFKF.mjs";
27
41
 
28
42
  // src/config.ts
29
43
  var ARCA_ENVIRONMENTS = ["production", "test"];
@@ -287,6 +301,686 @@ function defaultArcaLog(level, message, ...args) {
287
301
  method(message, ...args);
288
302
  }
289
303
 
304
+ // src/services/wsfe-derive.ts
305
+ var INVOICE_TYPES = {
306
+ A: ARCA_VOUCHER_TYPES.FACTURA_A,
307
+ B: ARCA_VOUCHER_TYPES.FACTURA_B,
308
+ C: ARCA_VOUCHER_TYPES.FACTURA_C
309
+ };
310
+ function deriveWsfeInvoice(input, now = /* @__PURE__ */ new Date()) {
311
+ assertIssueObject(input, "input");
312
+ assertIssueKeys(
313
+ input,
314
+ [
315
+ "issuer",
316
+ "items",
317
+ "salesPoint",
318
+ "to",
319
+ "total",
320
+ "date",
321
+ "currency",
322
+ "exchangeRate",
323
+ "service"
324
+ ],
325
+ "input"
326
+ );
327
+ if (typeof input.issuer !== "string" || !Object.hasOwn(ARCA_ISSUER_CONDITION_IDS, input.issuer)) {
328
+ invalid(
329
+ "issuer",
330
+ "responsable_inscripto, monotributo, exento, or no_alcanzado"
331
+ );
332
+ }
333
+ if (!Number.isSafeInteger(input.salesPoint) || input.salesPoint < 1 || input.salesPoint > 99999) {
334
+ invalid("salesPoint", "an integer from 1 through 99999");
335
+ }
336
+ const receiver = deriveReceiver(input.to);
337
+ const voucherClass = ARCA_INVOICE_CLASS_BY_ISSUER[input.issuer][input.to.condition];
338
+ const { data: amountsData, amounts } = calculateWsfeAmounts(input);
339
+ const currency = deriveCurrency(input);
340
+ if (input.to.condition === "consumidor_final" && receiver.documentType === ARCA_DOCUMENT_TYPES.CONSUMIDOR_FINAL) {
341
+ const [whole, fraction = ""] = currency.exchangeRate.split(".");
342
+ const rate = BigInt(whole) * 1000000n + BigInt(fraction.padEnd(6, "0"));
343
+ if (BigInt(amounts.sentTotal) * rate >= ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS * 1000000n) {
344
+ throw new ArcaInputError(
345
+ "The final consumer must be identified for this amount.",
346
+ {
347
+ code: "ARCA_INPUT_MISSING_FIELD",
348
+ field: "to",
349
+ expected: "cuit or dni for operations at or above ARS 10,000,000 (RG 5866)"
350
+ }
351
+ );
352
+ }
353
+ }
354
+ const voucherDate = normalizeWsfeDateInput(
355
+ input.date === void 0 ? buenosAiresDate(now) : input.date,
356
+ "date"
357
+ );
358
+ const data = {
359
+ salesPoint: input.salesPoint,
360
+ voucherType: INVOICE_TYPES[voucherClass],
361
+ voucherDate,
362
+ ...receiver,
363
+ ...currency,
364
+ ...amountsData,
365
+ ...deriveService(input.service, voucherDate)
366
+ };
367
+ try {
368
+ normalizeWsfeVoucherInput(data);
369
+ } catch (cause) {
370
+ throw new ArcaError(
371
+ "The derived invoice failed exact WSFE validation. This is an SDK invariant failure.",
372
+ "ARCA_ISSUE_INVARIANT",
373
+ { cause }
374
+ );
375
+ }
376
+ return { data, voucherClass, amounts };
377
+ }
378
+ function deriveReceiver(to) {
379
+ assertIssueObject(to, "to");
380
+ assertIssueKeys(to, ["condition", "cuit", "dni"], "to");
381
+ if (typeof to.condition !== "string" || !Object.hasOwn(ARCA_RECEIVER_CONDITION_IDS, to.condition)) {
382
+ invalid("to.condition", "one of the five supported receiver conditions");
383
+ }
384
+ if (to.cuit !== void 0 && to.dni !== void 0) {
385
+ invalid("to", "either cuit or dni, never both");
386
+ }
387
+ if (to.condition !== "consumidor_final" && to.cuit === void 0) {
388
+ throw new ArcaInputError(
389
+ "to.cuit is required for this receiver (WSFE 10063 for class A).",
390
+ {
391
+ code: "ARCA_INPUT_MISSING_FIELD",
392
+ field: "to.cuit",
393
+ expected: "an 11-digit CUIT"
394
+ }
395
+ );
396
+ }
397
+ const documentType = to.cuit === void 0 ? to.dni === void 0 ? ARCA_DOCUMENT_TYPES.CONSUMIDOR_FINAL : ARCA_DOCUMENT_TYPES.DNI : ARCA_DOCUMENT_TYPES.CUIT;
398
+ const documentNumber = to.cuit === void 0 ? to.dni === void 0 ? 0 : issueDocumentNumber(to.dni, "to.dni", 1, 11) : issueDocumentNumber(to.cuit, "to.cuit", 11, 11);
399
+ return {
400
+ documentType,
401
+ documentNumber,
402
+ receiverVatConditionId: ARCA_RECEIVER_CONDITION_IDS[to.condition]
403
+ };
404
+ }
405
+ function issueDocumentNumber(value, field, min, max) {
406
+ if (typeof value !== "number" && typeof value !== "string") {
407
+ invalid(field, `a positive document number with ${min} to ${max} digits`);
408
+ }
409
+ const text = String(value);
410
+ if (!/^\d+$/.test(text) || text.length < min || text.length > max || !Number.isSafeInteger(Number(text)) || Number(text) <= 0) {
411
+ invalid(field, `a positive document number with ${min} to ${max} digits`);
412
+ }
413
+ return Number(text);
414
+ }
415
+ function deriveCurrency(input) {
416
+ const currency = input.currency === void 0 ? "ARS" : input.currency;
417
+ if (currency !== "ARS" && currency !== "USD") {
418
+ invalid("currency", "ARS or USD");
419
+ }
420
+ if (input.exchangeRate !== void 0 && typeof input.exchangeRate !== "string") {
421
+ invalid("exchangeRate", "a decimal string");
422
+ }
423
+ if (currency === "USD" && input.exchangeRate === void 0) {
424
+ throw new ArcaInputError("exchangeRate is required for USD.", {
425
+ code: "ARCA_INPUT_MISSING_FIELD",
426
+ field: "exchangeRate",
427
+ expected: "a positive decimal string"
428
+ });
429
+ }
430
+ const exchangeRate = serializeArcaExchangeRate(
431
+ input.exchangeRate ?? "1",
432
+ "exchangeRate"
433
+ );
434
+ if (currency === "ARS" && exchangeRate !== "1") {
435
+ throw new ArcaInputError("exchangeRate must be 1 for ARS.", {
436
+ code: "ARCA_INPUT_INVALID_EXCHANGE_RATE",
437
+ field: "exchangeRate",
438
+ expected: "1 for ARS"
439
+ });
440
+ }
441
+ return { currencyId: ARCA_CURRENCY_IDS[currency], exchangeRate };
442
+ }
443
+ function deriveService(service, date) {
444
+ if (service === void 0) {
445
+ return { concept: 1 };
446
+ }
447
+ assertIssueObject(service, "service");
448
+ assertIssueKeys(service, ["from", "to", "dueDate"], "service");
449
+ for (const field of ["from", "to", "dueDate"]) {
450
+ if (service[field] === void 0) {
451
+ throw new ArcaInputError(`service.${field} is required.`, {
452
+ code: "ARCA_INPUT_MISSING_FIELD",
453
+ field: `service.${field}`,
454
+ expected: "a calendar date"
455
+ });
456
+ }
457
+ }
458
+ const serviceStartDate = normalizeWsfeDateInput(
459
+ service.from,
460
+ "service.from"
461
+ );
462
+ const serviceEndDate = normalizeWsfeDateInput(
463
+ service.to,
464
+ "service.to"
465
+ );
466
+ const paymentDueDate = normalizeWsfeDateInput(
467
+ service.dueDate,
468
+ "service.dueDate"
469
+ );
470
+ if (serviceEndDate < serviceStartDate) {
471
+ invalid("service.to", "a date on or after service.from");
472
+ }
473
+ if (paymentDueDate < date) {
474
+ invalid("service.dueDate", "a date on or after date");
475
+ }
476
+ return { concept: 2, serviceStartDate, serviceEndDate, paymentDueDate };
477
+ }
478
+ function buenosAiresDate(now) {
479
+ const parts = new Intl.DateTimeFormat("en-CA", {
480
+ timeZone: "America/Argentina/Buenos_Aires",
481
+ year: "numeric",
482
+ month: "2-digit",
483
+ day: "2-digit"
484
+ }).formatToParts(now);
485
+ return ["year", "month", "day"].map((part) => parts.find((entry) => entry.type === part)?.value).join("");
486
+ }
487
+ function assertIssueObject(value, field) {
488
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
489
+ invalid(field, "an object");
490
+ }
491
+ }
492
+ function assertIssueKeys(value, keys, prefix) {
493
+ for (const key of Object.keys(value)) {
494
+ if (!keys.includes(key)) {
495
+ const field = prefix === "input" ? key : `${prefix}.${key}`;
496
+ throw new ArcaInputError(
497
+ `${field} is not supported by vouchers.issue().`,
498
+ {
499
+ code: "ARCA_INPUT_RESERVED_FIELD",
500
+ field,
501
+ expected: "a supported facade field; use the exact API for other fiscal fields"
502
+ }
503
+ );
504
+ }
505
+ }
506
+ }
507
+ function invalid(field, expected) {
508
+ throw new ArcaInputError(`${field} must be ${expected}.`, {
509
+ code: "ARCA_INPUT_INVALID_VALUE",
510
+ field,
511
+ expected
512
+ });
513
+ }
514
+
515
+ // src/services/wsfe-identity.ts
516
+ function matchWsfeVoucherIdentity(sent, number, found) {
517
+ let missing;
518
+ const compare = (field, expected, actual, normalize) => {
519
+ if (actual === void 0 || actual === null || expected === void 0) {
520
+ missing ??= field;
521
+ return void 0;
522
+ }
523
+ try {
524
+ const left = normalize ? normalize(expected) : expected;
525
+ const right = normalize ? normalize(actual) : actual;
526
+ if (left !== right) {
527
+ return {
528
+ matches: false,
529
+ evidence: "conflict",
530
+ reason: `${field} differs from the sent input`
531
+ };
532
+ }
533
+ } catch {
534
+ missing ??= field;
535
+ }
536
+ return void 0;
537
+ };
538
+ const checks = [
539
+ ["voucherType", sent.voucherType, found.voucherType],
540
+ ["salesPoint", sent.salesPoint, found.salesPoint],
541
+ ["number", number, found.voucherNumber, normalizeVoucherNumber],
542
+ [
543
+ "date",
544
+ sent.voucherDate,
545
+ found.voucherDate,
546
+ (value) => normalizeWsfeDateInput(value, "date")
547
+ ],
548
+ ["concept", sent.concept, found.concept],
549
+ ["documentType", sent.documentType, found.documentType],
550
+ [
551
+ "documentNumber",
552
+ sent.documentNumber,
553
+ found.documentNumber,
554
+ normalizeDocument
555
+ ],
556
+ [
557
+ "receiverVatConditionId",
558
+ sent.receiverVatConditionId,
559
+ found.receiverVatConditionId
560
+ ],
561
+ ["currencyId", sent.currencyId, found.currencyId],
562
+ [
563
+ "exchangeRate",
564
+ sent.exchangeRate ?? (sent.currencyId === "PES" ? 1 : void 0),
565
+ found.exchangeRate,
566
+ (value) => serializeArcaExchangeRate(value, "exchangeRate")
567
+ ]
568
+ ];
569
+ for (const field of [
570
+ "totalAmount",
571
+ "netAmount",
572
+ "vatAmount",
573
+ "exemptAmount",
574
+ "nonTaxableAmount",
575
+ "taxAmount"
576
+ ]) {
577
+ checks.push([
578
+ field,
579
+ sent[field],
580
+ found[field],
581
+ (value) => normalizeArcaAmountToMinorUnits(value, field)
582
+ ]);
583
+ }
584
+ if (sent.concept === 2) {
585
+ for (const field of [
586
+ "serviceStartDate",
587
+ "serviceEndDate",
588
+ "paymentDueDate"
589
+ ]) {
590
+ checks.push([
591
+ field,
592
+ sent[field],
593
+ found[field],
594
+ (value) => normalizeWsfeDateInput(value, field)
595
+ ]);
596
+ }
597
+ }
598
+ for (const check of checks) {
599
+ const result = compare(...check);
600
+ if (result) {
601
+ return result;
602
+ }
603
+ }
604
+ const rates = compareVatRates(sent.vatRates ?? [], found.vatRates);
605
+ if (!rates.matches) {
606
+ if (rates.evidence === "conflict") {
607
+ return rates;
608
+ }
609
+ missing ??= rates.reason;
610
+ }
611
+ missing ??= incompleteAuthorization(sent, found);
612
+ return missing ? {
613
+ matches: false,
614
+ evidence: "incomplete",
615
+ reason: `Cannot verify ${missing}`
616
+ } : { matches: true };
617
+ }
618
+ function incompleteAuthorization(sent, found) {
619
+ let missing;
620
+ if (sent.concept !== 1 && sent.concept !== 2) {
621
+ missing ??= "unsupported concept";
622
+ }
623
+ for (const field of [
624
+ "taxes",
625
+ "associatedVouchers",
626
+ "associatedPeriod",
627
+ "optionalFields",
628
+ "buyers",
629
+ "activities",
630
+ "sameCurrencyForeignCancellation"
631
+ ]) {
632
+ const value = sent[field];
633
+ if (value !== void 0 && (!Array.isArray(value) || value.length > 0)) {
634
+ missing ??= `unsupported exact field ${field}`;
635
+ }
636
+ }
637
+ if (!(found.result === "A" || found.result === "O")) {
638
+ missing ??= "authorized result";
639
+ }
640
+ if (!found.cae?.trim()) {
641
+ missing ??= "cae";
642
+ }
643
+ if (!found.caeExpiry?.trim()) {
644
+ missing ??= "caeExpiry";
645
+ }
646
+ return missing;
647
+ }
648
+ function normalizeVoucherNumber(value) {
649
+ if (!Number.isSafeInteger(value) || value < 1 || value > 99999999) {
650
+ throw new Error("Invalid voucher number");
651
+ }
652
+ return value;
653
+ }
654
+ function normalizeDocument(value) {
655
+ const text = String(value);
656
+ if (!/^\d+$/.test(text)) {
657
+ throw new Error("Invalid document number");
658
+ }
659
+ return BigInt(text);
660
+ }
661
+ function compareVatRates(expected, actual) {
662
+ if (actual === void 0) {
663
+ return expected.length === 0 ? { matches: true } : { matches: false, evidence: "incomplete", reason: "vatRates" };
664
+ }
665
+ if (actual.length !== expected.length || new Set(actual.map((rate) => rate.id)).size !== actual.length) {
666
+ return {
667
+ matches: false,
668
+ evidence: "conflict",
669
+ reason: "vatRates ids differ from the sent input"
670
+ };
671
+ }
672
+ for (const rate of expected) {
673
+ const found = actual.find((item) => item.id === rate.id);
674
+ if (!found) {
675
+ return {
676
+ matches: false,
677
+ evidence: "conflict",
678
+ reason: `vatRates id ${rate.id} differs from the sent input`
679
+ };
680
+ }
681
+ for (const field of ["baseAmount", "amount"]) {
682
+ try {
683
+ if (normalizeArcaAmountToMinorUnits(rate[field], field) !== normalizeArcaAmountToMinorUnits(found[field], field)) {
684
+ return {
685
+ matches: false,
686
+ evidence: "conflict",
687
+ reason: `vatRates[${rate.id}].${field} differs from the sent input`
688
+ };
689
+ }
690
+ } catch {
691
+ return {
692
+ matches: false,
693
+ evidence: "incomplete",
694
+ reason: `vatRates[${rate.id}].${field}`
695
+ };
696
+ }
697
+ }
698
+ }
699
+ return { matches: true };
700
+ }
701
+ function toVoucherSummary(found) {
702
+ const summary = { number: found.voucherNumber };
703
+ for (const field of [
704
+ "salesPoint",
705
+ "voucherType",
706
+ "concept",
707
+ "documentType",
708
+ "documentNumber",
709
+ "receiverVatConditionId",
710
+ "currencyId",
711
+ "exchangeRate",
712
+ "totalAmount",
713
+ "netAmount",
714
+ "vatAmount",
715
+ "exemptAmount",
716
+ "nonTaxableAmount",
717
+ "taxAmount",
718
+ "serviceStartDate",
719
+ "serviceEndDate",
720
+ "paymentDueDate",
721
+ "result",
722
+ "cae",
723
+ "caeExpiry"
724
+ ]) {
725
+ if (found[field] !== void 0) {
726
+ Object.assign(summary, { [field]: found[field] });
727
+ }
728
+ }
729
+ if (found.voucherDate !== void 0) {
730
+ summary.date = found.voucherDate;
731
+ }
732
+ if (found.vatRates !== void 0) {
733
+ summary.vatRates = found.vatRates.map(({ id, baseAmount, amount }) => ({
734
+ id,
735
+ baseAmount,
736
+ amount
737
+ }));
738
+ }
739
+ return summary;
740
+ }
741
+
742
+ // src/services/vouchers.ts
743
+ var SERIALIZATION_NOTICE = "Serialize calls per (representedTaxId, salesPoint, voucherType). The SDK does not coordinate writers; uncoordinated calls collide on 10016. Servers and queues must persist attempts and use wsfe.authorizeVoucherOutcome().";
744
+ function createVouchersService(wsfe) {
745
+ return {
746
+ issue: async (input, options) => {
747
+ const result = await issueInvoice(
748
+ wsfe,
749
+ input,
750
+ options === void 0 ? {} : options
751
+ );
752
+ return result;
753
+ }
754
+ };
755
+ }
756
+ async function issueInvoice(wsfe, input, options) {
757
+ validateOptions(options);
758
+ const { data, voucherClass, amounts } = deriveWsfeInvoice(input);
759
+ const auth = {
760
+ representedTaxId: options.representedTaxId,
761
+ forceRefresh: options.forceRefresh
762
+ };
763
+ const includeRaw = options.include?.raw === true;
764
+ const includeExact = options.include?.exactInput === true;
765
+ const number = await wsfe.getNextVoucherNumber({
766
+ ...auth,
767
+ salesPoint: data.salesPoint,
768
+ voucherType: data.voucherType
769
+ });
770
+ if (!Number.isSafeInteger(number) || number < 1 || number > 99999999) {
771
+ throw new ArcaServiceError(
772
+ "WSFE returned an invalid next voucher number.",
773
+ {
774
+ service: "wsfe",
775
+ operation: "FECompUltimoAutorizado"
776
+ }
777
+ );
778
+ }
779
+ const attempted = {
780
+ salesPoint: data.salesPoint,
781
+ voucherType: data.voucherType,
782
+ number
783
+ };
784
+ const exact = includeExact ? { sent: data } : {};
785
+ const authorization = await wsfe.authorizeVoucherOutcome({
786
+ ...auth,
787
+ data,
788
+ voucherNumber: number
789
+ });
790
+ const voucher = (cae, caeExpiry) => ({
791
+ ...attempted,
792
+ voucherClass,
793
+ date: data.voucherDate,
794
+ cae,
795
+ caeExpiry,
796
+ amounts
797
+ });
798
+ if (authorization.kind === "authorized" && authorization.caeExpiry && authorization.voucherNumber === number) {
799
+ return {
800
+ kind: "authorized",
801
+ recoveredByMatch: false,
802
+ voucher: voucher(authorization.cae, authorization.caeExpiry),
803
+ authorization: projectEvidence(authorization, includeRaw),
804
+ ...exact
805
+ };
806
+ }
807
+ if (authorization.kind === "rejected") {
808
+ return {
809
+ kind: "rejected",
810
+ attempted,
811
+ issues: [...authorization.errors, ...authorization.observations].map(
812
+ projectIssue
813
+ ),
814
+ authorization: projectEvidence(authorization, includeRaw)
815
+ };
816
+ }
817
+ const uncertain = authorization.kind === "indeterminate" ? authorization : {
818
+ ...authorization,
819
+ kind: "indeterminate",
820
+ reason: authorization.voucherNumber === number ? "incomplete_response" : "contradictory_response"
821
+ };
822
+ const attempt = projectEvidence(uncertain, includeRaw);
823
+ return recoverInvoice({
824
+ wsfe,
825
+ auth,
826
+ data,
827
+ attempted,
828
+ attempt,
829
+ includeRaw,
830
+ exact,
831
+ voucher
832
+ });
833
+ }
834
+ async function recoverInvoice({
835
+ wsfe,
836
+ auth,
837
+ data,
838
+ attempted,
839
+ attempt,
840
+ includeRaw,
841
+ exact,
842
+ voucher
843
+ }) {
844
+ let lookup;
845
+ try {
846
+ lookup = await wsfe.lookupVoucher({ ...auth, ...attempted });
847
+ } catch (error) {
848
+ return {
849
+ kind: "indeterminate",
850
+ attempted,
851
+ attempt,
852
+ lookup: { kind: "failed", error: toArcaSafeErrorMetadata(error) }
853
+ };
854
+ }
855
+ const raw = includeRaw ? { raw: lookup.raw } : {};
856
+ if (lookup.kind === "not_found") {
857
+ return {
858
+ kind: "indeterminate",
859
+ attempted,
860
+ attempt,
861
+ lookup: { kind: "not_found", ...raw }
862
+ };
863
+ }
864
+ const matched = matchWsfeVoucherIdentity(
865
+ data,
866
+ attempted.number,
867
+ lookup.voucher
868
+ );
869
+ if (!matched.matches) {
870
+ if (matched.evidence === "conflict") {
871
+ return {
872
+ kind: "conflict",
873
+ attempted,
874
+ attempt,
875
+ found: { ...toVoucherSummary(lookup.voucher), ...raw },
876
+ reason: `${matched.reason}. ${SERIALIZATION_NOTICE}`
877
+ };
878
+ }
879
+ return {
880
+ kind: "indeterminate",
881
+ attempted,
882
+ attempt,
883
+ lookup: { kind: "incomplete", reason: matched.reason, ...raw }
884
+ };
885
+ }
886
+ return {
887
+ kind: "authorized",
888
+ recoveredByMatch: true,
889
+ voucher: voucher(
890
+ lookup.voucher.cae,
891
+ lookup.voucher.caeExpiry
892
+ ),
893
+ attempt,
894
+ lookup: { ...toVoucherSummary(lookup.voucher), ...raw },
895
+ ...exact
896
+ };
897
+ }
898
+ function projectIssue(issue) {
899
+ return {
900
+ service: issue.service,
901
+ operation: issue.operation,
902
+ source: issue.source,
903
+ category: issue.category,
904
+ message: issue.message,
905
+ ...issue.code === void 0 ? {} : { code: issue.code },
906
+ ...issue.resultLevel === void 0 ? {} : { resultLevel: issue.resultLevel }
907
+ };
908
+ }
909
+ function projectEvidence(evidence, includeRaw) {
910
+ const base = {
911
+ kind: evidence.kind,
912
+ service: evidence.service,
913
+ operation: evidence.operation,
914
+ results: {
915
+ ...evidence.results.header === void 0 ? {} : { header: evidence.results.header },
916
+ ...evidence.results.detail === void 0 ? {} : { detail: evidence.results.detail },
917
+ ...evidence.results.operation === void 0 ? {} : { operation: evidence.results.operation }
918
+ },
919
+ errors: evidence.errors.map(projectIssue),
920
+ observations: evidence.observations.map(projectIssue),
921
+ ...includeRaw && evidence.raw !== void 0 ? { raw: evidence.raw } : {}
922
+ };
923
+ const projected = { ...base };
924
+ for (const field of [
925
+ "result",
926
+ "resultLevel",
927
+ "cae",
928
+ "caeExpiry",
929
+ "voucherNumber",
930
+ "reason"
931
+ ]) {
932
+ if (field in evidence && evidence[field] !== void 0) {
933
+ projected[field] = evidence[field];
934
+ }
935
+ }
936
+ if (evidence.kind === "indeterminate" && evidence.authentication) {
937
+ const { code, reason, providerCode } = evidence.authentication;
938
+ projected.authentication = {
939
+ code,
940
+ reason,
941
+ ...providerCode === void 0 ? {} : { providerCode }
942
+ };
943
+ }
944
+ return projected;
945
+ }
946
+ function validateOptions(options) {
947
+ assertIssueObject(options, "options");
948
+ assertIssueKeys(
949
+ options,
950
+ ["representedTaxId", "forceRefresh", "include"],
951
+ "options"
952
+ );
953
+ if (options.representedTaxId !== void 0) {
954
+ issueDocumentNumber(
955
+ options.representedTaxId,
956
+ "options.representedTaxId",
957
+ 11,
958
+ 11
959
+ );
960
+ }
961
+ if (options.forceRefresh !== void 0 && typeof options.forceRefresh !== "boolean") {
962
+ throw new ArcaInputError("options.forceRefresh must be a boolean.", {
963
+ code: "ARCA_INPUT_INVALID_VALUE",
964
+ field: "options.forceRefresh"
965
+ });
966
+ }
967
+ if (options.include !== void 0) {
968
+ assertIssueObject(options.include, "options.include");
969
+ assertIssueKeys(options.include, ["raw", "exactInput"], "options.include");
970
+ for (const field of ["raw", "exactInput"]) {
971
+ if (options.include[field] !== void 0 && typeof options.include[field] !== "boolean") {
972
+ throw new ArcaInputError(
973
+ `options.include.${field} must be a boolean.`,
974
+ {
975
+ code: "ARCA_INPUT_INVALID_VALUE",
976
+ field: `options.include.${field}`
977
+ }
978
+ );
979
+ }
980
+ }
981
+ }
982
+ }
983
+
290
984
  // src/internal/http.ts
291
985
  import https from "https";
292
986
  var defaultAgent = new https.Agent({
@@ -1134,9 +1828,11 @@ function createArcaClient(config) {
1134
1828
  retries: normalizedConfig.retries,
1135
1829
  retryDelay: normalizedConfig.retryDelay
1136
1830
  });
1831
+ const wsfe = createWsfeService({ config: normalizedConfig, auth, soap });
1137
1832
  return {
1138
1833
  config: publicConfig,
1139
- wsfe: createWsfeService({ config: normalizedConfig, auth, soap }),
1834
+ wsfe,
1835
+ vouchers: createVouchersService(wsfe),
1140
1836
  wsmtxca: createWsmtxcaService({ config: normalizedConfig, auth, soap }),
1141
1837
  padron: createPadronService({ config: normalizedConfig, auth, soap })
1142
1838
  };
@@ -1144,6 +1840,10 @@ function createArcaClient(config) {
1144
1840
  export {
1145
1841
  ARCA_ENVIRONMENTS,
1146
1842
  ARCA_ENV_VARIABLES,
1843
+ ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS,
1844
+ ARCA_INVOICE_CLASS_BY_ISSUER,
1845
+ ARCA_ISSUER_CONDITION_IDS,
1846
+ ARCA_RECEIVER_CONDITION_IDS,
1147
1847
  ArcaAuthenticationError,
1148
1848
  ArcaConfigurationError,
1149
1849
  ArcaError,
@@ -1162,6 +1862,8 @@ export {
1162
1862
  createWsfeService,
1163
1863
  createWsmtxcaService,
1164
1864
  isArcaAuthenticationError,
1165
- resolveArcaEnvironment
1865
+ matchWsfeVoucherIdentity,
1866
+ resolveArcaEnvironment,
1867
+ toArcaSafeErrorMetadata
1166
1868
  };
1167
1869
  //# sourceMappingURL=index.mjs.map