@deuriib/dgii-ecf 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -66,6 +66,7 @@ __export(index_exports, {
66
66
  isRetryableStatus: () => isRetryableStatus,
67
67
  ok: () => import_neverthrow.ok,
68
68
  okAsync: () => import_neverthrow.okAsync,
69
+ roundHalfUpToCents: () => roundHalfUpToCents,
69
70
  toDgiiError: () => toDgiiError,
70
71
  validateXMLCertificate: () => validateXMLCertificate
71
72
  });
@@ -521,17 +522,15 @@ var P12Reader = class {
521
522
  return import_node_forge.default.pkcs12.pkcs12FromAsn1(asn1, false, this.passphrase);
522
523
  }
523
524
  extractKey(p12) {
524
- const keyBags = p12.getBags({
525
- bagType: import_node_forge.default.pki.oids.pkcs8ShroudedKeyBag
526
- });
527
- const pkcs8Key = keyBags[import_node_forge.default.pki.oids.pkcs8ShroudedKeyBag]?.[0];
528
- if (pkcs8Key?.key) {
529
- return import_node_forge.default.pki.privateKeyToPem(pkcs8Key.key);
530
- }
531
- const certBags = p12.getBags({ bagType: import_node_forge.default.pki.oids.certBag });
532
- const certBag = certBags[import_node_forge.default.pki.oids.certBag]?.[0];
533
- if (certBag?.key) {
534
- return import_node_forge.default.pki.privateKeyToPem(certBag.key);
525
+ const keyBagTypes = [
526
+ import_node_forge.default.pki.oids.pkcs8ShroudedKeyBag,
527
+ import_node_forge.default.pki.oids.keyBag
528
+ ];
529
+ for (const bagType of keyBagTypes) {
530
+ const bag = p12.getBags({ bagType })[bagType]?.[0];
531
+ if (bag?.key) {
532
+ return import_node_forge.default.pki.privateKeyToPem(bag.key);
533
+ }
535
534
  }
536
535
  return void 0;
537
536
  }
@@ -698,8 +697,19 @@ var Signature = class {
698
697
  privateKey;
699
698
  certificatePem;
700
699
  signXml(xml, rootElName) {
700
+ let parsed;
701
+ try {
702
+ parsed = parseStrict(xml);
703
+ } catch (error) {
704
+ return (0, import_neverthrow.err)(
705
+ new DgiiError(
706
+ error instanceof Error ? error.message : `Invalid XML: ${String(error)}`,
707
+ { code: "INVALID_XML", cause: error }
708
+ )
709
+ );
710
+ }
701
711
  try {
702
- const { doc, rootName } = parseStrict(xml);
712
+ const { doc, rootName } = parsed;
703
713
  const elementName = rootElName ?? rootName;
704
714
  const sig = new import_xml_crypto.SignedXml({
705
715
  privateKey: this.privateKey,
@@ -728,9 +738,10 @@ var Signature = class {
728
738
  }
729
739
  }
730
740
  };
741
+ var X509_CERTIFICATE_RE = /<(?:[\w]+:)?X509Certificate>([\s\S]*?)<\/(?:[\w]+:)?X509Certificate>/;
731
742
  var validateXMLCertificate = (xml) => {
732
743
  try {
733
- const match = xml.match(/<X509Certificate>([\s\S]*?)<\/X509Certificate>/);
744
+ const match = xml.match(X509_CERTIFICATE_RE);
734
745
  if (!match?.[1]) {
735
746
  return { isValid: false, error: "X509Certificate not found" };
736
747
  }
@@ -758,6 +769,35 @@ var validateXMLCertificate = (xml) => {
758
769
 
759
770
  // src/transformer.ts
760
771
  var import_xml_js = __toESM(require("xml-js"), 1);
772
+ var MONETARY_RE = /^(-?)(\d+)\.(\d+)$/;
773
+ var incrementDigits = (digits) => {
774
+ const chars = digits.split("");
775
+ let index = chars.length - 1;
776
+ while (index >= 0) {
777
+ const current = chars[index];
778
+ if (current === "9") {
779
+ chars[index] = "0";
780
+ index -= 1;
781
+ continue;
782
+ }
783
+ chars[index] = String(Number(current) + 1);
784
+ return chars.join("");
785
+ }
786
+ return `1${chars.join("")}`;
787
+ };
788
+ var roundHalfUpToCents = (value) => {
789
+ const match = MONETARY_RE.exec(value);
790
+ if (!match) {
791
+ return value;
792
+ }
793
+ const sign = match[1] === "-" ? "-" : "";
794
+ const integerPart = (match[2] ?? "0").replace(/^0+(?=\d)/, "");
795
+ const fractionPart = `${match[3] ?? ""}000`;
796
+ const cents = `${integerPart}${fractionPart.slice(0, 2)}`;
797
+ const rounded = fractionPart[2] >= "5" ? incrementDigits(cents) : cents;
798
+ const padded = rounded.padStart(3, "0");
799
+ return `${sign}${padded.slice(0, -2)}.${padded.slice(-2)}`;
800
+ };
761
801
  var Transformer = class {
762
802
  json2xml(dataObject, round = false) {
763
803
  try {
@@ -771,9 +811,8 @@ var Transformer = class {
771
811
  spaces: 2,
772
812
  fullTagEmptyElement: true,
773
813
  textFn: (value, label) => {
774
- const omits = ["version"];
775
- if (/^\d+\.\d+$/.test(value) && round && !omits.includes(label.toLowerCase())) {
776
- return parseFloat(value).toFixed(2);
814
+ if (round && label.toLowerCase() !== "version") {
815
+ return roundHalfUpToCents(value);
777
816
  }
778
817
  return value;
779
818
  }
@@ -808,8 +847,9 @@ var Transformer = class {
808
847
  };
809
848
 
810
849
  // src/utils.ts
850
+ var SIGNATURE_VALUE_RE = /<(?:[\w]+:)?SignatureValue>([\s\S]*?)<\/(?:[\w]+:)?SignatureValue>/;
811
851
  var getCodeSixDigitfromSignature = (signedXml) => {
812
- const match = signedXml.match(/<SignatureValue>([\s\S]*?)<\/SignatureValue>/);
852
+ const match = signedXml.match(SIGNATURE_VALUE_RE);
813
853
  const value = match?.[1]?.trim();
814
854
  if (!value) {
815
855
  return (0, import_neverthrow.err)(new DgiiError("SignatureValue not found", { code: "SIGNING" }));
@@ -1167,7 +1207,15 @@ var ECF = class {
1167
1207
  return (0, import_neverthrow.ok)(Array.isArray(data) ? data : [data]);
1168
1208
  }
1169
1209
  /** RFCE inquiry — DGII production only. */
1170
- getSummaryInvoiceInquiry(rnc, encf, codSeguridad) {
1210
+ async getSummaryInvoiceInquiry(rnc, encf, codSeguridad) {
1211
+ if (this.environment !== "eCF" /* Prod */) {
1212
+ return (0, import_neverthrow.err)(
1213
+ new DgiiError(
1214
+ `getSummaryInvoiceInquiry is only available in the production environment (eCF); current environment is ${this.environment}`,
1215
+ { code: "VALIDATION" }
1216
+ )
1217
+ );
1218
+ }
1171
1219
  const url = buildUrl(
1172
1220
  this.environment,
1173
1221
  "consultarfce/api/Consultas/Consulta" /* InquiryInvoiceSummary */,
@@ -1234,6 +1282,7 @@ var ECF = class {
1234
1282
  isRetryableStatus,
1235
1283
  ok,
1236
1284
  okAsync,
1285
+ roundHalfUpToCents,
1237
1286
  toDgiiError,
1238
1287
  validateXMLCertificate
1239
1288
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/environment.ts","../src/types.ts","../src/errors.ts","../src/result.ts","../src/resilience.ts","../src/http.ts","../src/certificate.ts","../src/signing.ts","../src/transformer.ts","../src/utils.ts","../src/client.ts"],"sourcesContent":["export * from './environment.js';\nexport * from './types.js';\nexport * from './errors.js';\nexport * from './result.js';\nexport * from './resilience.js';\nexport * from './http.js';\nexport * from './certificate.js';\nexport * from './signing.js';\nexport * from './transformer.js';\nexport * from './utils.js';\nexport * from './client.js';\n","export enum Environment {\n /** DGII test environment */\n Dev = 'TesteCF',\n /** DGII certification environment */\n Cert = 'CerteCF',\n /** DGII production environment */\n Prod = 'eCF',\n}\n\nexport const BaseUrl = {\n /** Crédito fiscal / general e-CF services */\n ECF: 'https://ecf.dgii.gov.do',\n /** Factura de consumo (< DOP 250,000) */\n CF: 'https://fc.dgii.gov.do',\n /** DGII service status */\n STATUS: 'https://statusecf.dgii.gov.do',\n} as const;\n\nexport type BaseUrlKey = keyof typeof BaseUrl;\n\nexport enum Endpoint {\n Seed = 'Autenticacion/api/Autenticacion/Semilla',\n ValidateSeed = 'autenticacion/api/Autenticacion/ValidarSemilla',\n SendInvoice = 'recepcion/api/FacturasElectronicas',\n SendSummary = 'recepcionfc/api/recepcion/ecf',\n InquiryInvoiceSummary = 'consultarfce/api/Consultas/Consulta',\n CommercialApproval = 'aprobacionComercial/api/AprobacionComercial',\n TrackResultStatus = 'consultaresultado/api/Consultas/Estado',\n InquiryStatus = 'consultaestado/api/Consultas/Estado',\n AllTrackingEcf = 'ConsultaTrackIds/api/TrackIds/Consulta',\n Directory = 'consultadirectorio/api/consultas/obtenerdirectorioporrnc',\n Void = 'anulacionrangos/api/operaciones/anularrango',\n}\n\n/** Endpoints used when talking to a buyer's Sender↔Receiver host. */\nexport enum SenderReceiverEndpoint {\n Seed = 'fe/autenticacion/api/semilla',\n ValidateSeed = 'fe/autenticacion/api/validacioncertificado',\n SendInvoice = 'fe/recepcion/api/ecf',\n CommercialApproval = 'fe/aprobacioncomercial/api/ecf',\n}\n\n/** Build an absolute DGII URL: `${baseUrl}/${environment}/${endpoint}`. */\nexport const buildUrl = (\n environment: Environment,\n endpoint: Endpoint,\n baseUrl: string = BaseUrl.ECF,\n): string => `${baseUrl.replace(/\\/+$/, '')}/${environment}/${endpoint}`;\n\n/** Build an absolute Sender↔Receiver URL against a buyer host. */\nexport const buildSenderReceiverUrl = (\n host: string,\n endpoint: SenderReceiverEndpoint,\n): string => `${host.replace(/\\/+$/, '')}/${endpoint}`;\n","export interface Mensaje {\n valor: string;\n codigo: number;\n}\n\nexport interface AuthToken {\n token: string;\n expira: string;\n expedido: string;\n}\n\nexport enum TrackStatusEnum {\n NotFound = 'No encontrado',\n Accepted = 'Aceptado',\n Rejected = 'Rechazado',\n InProcess = 'En Proceso',\n ConditionalAccepted = 'Aceptado Condicional',\n}\n\nexport type TrackStatusCode = 0 | 1 | 2 | 3 | 4;\n\nexport interface TrackingStatusResponse {\n trackId: string;\n codigo: TrackStatusCode;\n estado: TrackStatusEnum;\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n fechaRecepcion: string;\n mensajes?: Mensaje[];\n}\n\nexport type InquiryStatusCode = 0 | 1 | 2;\n\nexport type InquiryStatus = 'No encontrado' | 'Aceptado' | 'Rechazado';\n\nexport interface InquiryStatusResponse {\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n rncEmisor?: string;\n ncfElectronico?: string;\n montoTotal?: number;\n totalITBIS?: number;\n fechaEmision?: string;\n fechaFirma?: string;\n rncComprador?: string;\n codigoSeguridad?: string;\n idExtranjero?: string;\n}\n\nexport interface SummaryTrackingStatusResponse {\n trackId: string;\n estado: string;\n fechaRecepcion: string;\n}\n\nexport interface InvoiceResponse {\n trackId?: string;\n error?: string;\n mensajes?: Mensaje[];\n}\n\nexport interface InvoiceSummaryResponse {\n codigo: number;\n estado: 'Aceptado' | 'Rechazado' | 'Aceptado Condicional';\n mensajes?: Mensaje[];\n encf: string;\n secuenciaUtilizada: boolean;\n}\n\nexport interface ServiceDirectoryResponse {\n nombre: string;\n rnc: string;\n urlRecepcion: string;\n urlAceptacion: string;\n urlOpcional: string;\n}\n\nexport interface InquiryInvoiceSummary {\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n mensajes?: Mensaje[];\n}\n\nexport interface CommercialApprovalResponse {\n codigo: '01' | '02';\n estado: 'Aprobación Comercial Aprobada.' | 'Aprobacion Comercial Rechazada.';\n mensaje: string[];\n}\n\nexport interface VoidNCFResponse {\n rnc: string;\n codigo: string;\n nombre: string;\n mensajes: string[];\n}\n","import type { Mensaje } from './types.js';\n\nexport type DgiiErrorCode =\n | 'INVALID_XML'\n | 'CERTIFICATE'\n | 'SIGNING'\n | 'HTTP'\n | 'AUTH'\n | 'TIMEOUT'\n | 'CIRCUIT_OPEN'\n | 'IDEMPOTENCY'\n | 'VALIDATION'\n | 'UNKNOWN';\n\nconst RETRYABLE_STATUSES = new Set<number>([408, 429, 500, 502, 503, 504]);\n\nexport const isRetryableStatus = (status: number | undefined): boolean =>\n status !== undefined && RETRYABLE_STATUSES.has(status);\n\nexport interface DgiiErrorOptions {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n data?: unknown;\n mensajes?: Mensaje[];\n retryable?: boolean;\n cause?: unknown;\n}\n\nconst MAX_RAW = 1000;\n\nconst truncate = (value: string): string =>\n value.length > MAX_RAW ? `${value.slice(0, MAX_RAW)}…` : value;\n\nconst collapseWhitespace = (value: string): string =>\n value.replace(/\\s+/g, ' ').trim();\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst looksLikeHtml = (value: string): boolean =>\n /^\\s*<(?:!doctype|html|body|head)\\b/i.test(value);\n\nconst stripHtml = (value: string): string =>\n collapseWhitespace(\n value\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<[^>]+>/g, ' '),\n );\n\nconst readMensajes = (value: unknown): Mensaje[] | undefined => {\n if (!Array.isArray(value) || value.length === 0) {\n return undefined;\n }\n const out: Mensaje[] = [];\n for (const item of value) {\n if (typeof item === 'string' && item.trim()) {\n out.push({ valor: item.trim(), codigo: 0 });\n } else if (isObject(item) && typeof item.valor === 'string') {\n out.push({\n valor: item.valor,\n codigo: typeof item.codigo === 'number' ? item.codigo : 0,\n });\n }\n }\n return out.length ? out : undefined;\n};\n\nconst MESSAGE_KEYS = [\n 'mensaje',\n 'Mensaje',\n 'message',\n 'Message',\n 'error',\n 'Error',\n 'errorMessage',\n 'error_description',\n 'detail',\n 'Detail',\n 'title',\n 'Title',\n 'descripcion',\n 'Descripcion',\n];\n\n/**\n * Reduce DGII's inconsistent error payloads (bare string, `{ mensajes }`,\n * ASP.NET ProblemDetails/ModelState, or an HTML page) to a single message.\n */\nexport const extractDgiiErrorMessage = (\n data: unknown,\n seen: WeakSet<object> = new WeakSet<object>(),\n): string | undefined => {\n if (data === undefined || data === null) {\n return undefined;\n }\n\n if (typeof data === 'string') {\n const trimmed = data.trim();\n if (!trimmed) {\n return undefined;\n }\n if (/^[[{\"]/.test(trimmed)) {\n try {\n return extractDgiiErrorMessage(JSON.parse(trimmed), seen);\n } catch {\n // Not JSON after all — fall through to raw text.\n }\n }\n if (looksLikeHtml(trimmed)) {\n const text = stripHtml(trimmed);\n return text ? truncate(text) : undefined;\n }\n return truncate(collapseWhitespace(trimmed));\n }\n\n if (typeof data === 'number' || typeof data === 'boolean') {\n return String(data);\n }\n\n if (data instanceof Error) {\n return data.message || undefined;\n }\n\n if (Array.isArray(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n const parts = data\n .map((item) => extractDgiiErrorMessage(item, seen))\n .filter((item): item is string => Boolean(item));\n return parts.length ? truncate(parts.join(' | ')) : undefined;\n }\n\n if (isObject(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n\n const mensajes = readMensajes(data.mensajes ?? data.Mensajes);\n if (mensajes) {\n return truncate(mensajes.map((mensaje) => mensaje.valor).join(' | '));\n }\n\n for (const key of MESSAGE_KEYS) {\n const value = data[key];\n if (typeof value === 'string' && value.trim()) {\n return truncate(collapseWhitespace(value));\n }\n if (key === 'error' && (isObject(value) || Array.isArray(value))) {\n const nested = extractDgiiErrorMessage(value, seen);\n if (nested) {\n return nested;\n }\n }\n }\n\n const errors = data.errors ?? data.Errors;\n if (isObject(errors)) {\n const parts = Object.entries(errors)\n .map(([field, value]) => {\n const nested = extractDgiiErrorMessage(value, seen);\n return nested ? `${field}: ${nested}` : undefined;\n })\n .filter((item): item is string => Boolean(item));\n if (parts.length) {\n return truncate(parts.join(' | '));\n }\n } else if (errors) {\n const nested = extractDgiiErrorMessage(errors, seen);\n if (nested) {\n return nested;\n }\n }\n\n try {\n const serialized = JSON.stringify(data);\n if (serialized && serialized !== '{}') {\n return truncate(serialized);\n }\n } catch {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport class DgiiError extends Error {\n readonly code: DgiiErrorCode;\n readonly status?: number;\n readonly statusText?: string;\n readonly resource?: string;\n readonly method?: string;\n readonly baseURL?: string;\n readonly data?: unknown;\n readonly mensajes?: Mensaje[];\n readonly retryable: boolean;\n\n constructor(message: string, options: DgiiErrorOptions = {}) {\n super(message);\n this.name = 'DgiiError';\n Object.setPrototypeOf(this, DgiiError.prototype);\n\n this.code = options.code ?? 'UNKNOWN';\n this.status = options.status;\n this.statusText = options.statusText;\n this.resource = options.resource;\n this.method = options.method;\n this.baseURL = options.baseURL;\n this.data = options.data;\n this.mensajes = options.mensajes;\n this.retryable = options.retryable ?? isRetryableStatus(options.status);\n\n if (options.cause !== undefined) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n statusText: this.statusText,\n resource: this.resource,\n method: this.method,\n mensajes: this.mensajes,\n data: this.data,\n };\n }\n}\n\nexport interface DgiiErrorContext {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n fallbackMessage?: string;\n}\n\n/** Normalize any thrown value into a {@link DgiiError}. */\nexport const toDgiiError = (\n err: unknown,\n context: DgiiErrorContext = {},\n): DgiiError => {\n if (err instanceof DgiiError) {\n return err;\n }\n\n if (err instanceof Error) {\n return new DgiiError(\n err.message || context.fallbackMessage || 'DGII request failed',\n {\n ...context,\n cause: err,\n },\n );\n }\n\n const message =\n extractDgiiErrorMessage(err) ||\n context.fallbackMessage ||\n 'DGII request failed';\n const status =\n isObject(err) && typeof err.status === 'number'\n ? err.status\n : context.status;\n\n return new DgiiError(message, {\n ...context,\n status,\n data: err,\n mensajes: isObject(err)\n ? readMensajes(err.mensajes ?? err.Mensajes)\n : undefined,\n cause: err,\n });\n};\n","import type { Result } from 'neverthrow';\nimport type { DgiiError } from './errors.js';\n\nexport type { Result } from 'neverthrow';\n\nexport {\n Ok,\n Err,\n ok,\n err,\n okAsync,\n errAsync,\n fromThrowable,\n fromPromise,\n fromSafePromise,\n ResultAsync,\n} from 'neverthrow';\n\n/** A {@link Result} whose failure channel is always {@link DgiiError}. */\nexport type DgiiResult<T> = Result<T, DgiiError>;\n","import {\n ConsecutiveBreaker,\n ExponentialBackoff,\n TimeoutStrategy,\n bulkhead,\n circuitBreaker,\n handleAll,\n handleWhen,\n retry,\n timeout,\n wrap,\n type IPolicy,\n} from 'cockatiel';\nimport { DgiiError } from './errors.js';\n\nexport interface ResilienceOptions {\n /** Maximum number of attempts (including the first). Default 3. */\n maxRetries?: number;\n /** Consecutive failures before the circuit opens. Default 5. */\n breakerThreshold?: number;\n /** Milliseconds the circuit stays open before half-opening. Default 30s. */\n halfOpenAfterMs?: number;\n /** Per-attempt timeout in milliseconds. Default 15s. */\n timeoutMs?: number;\n /** Initial retry backoff delay in milliseconds. Default 100. */\n retryInitialDelayMs?: number;\n /** Maximum concurrent in-flight requests. Default 20. */\n bulkheadLimit?: number;\n /** Maximum queued requests while the bulkhead is saturated. Default 40. */\n bulkheadQueue?: number;\n}\n\nexport const defaultResilienceOptions: Required<ResilienceOptions> = {\n maxRetries: 3,\n breakerThreshold: 5,\n halfOpenAfterMs: 30_000,\n timeoutMs: 15_000,\n retryInitialDelayMs: 100,\n bulkheadLimit: 20,\n bulkheadQueue: 40,\n};\n\n/**\n * Only transient failures are retried: network errors, timeouts, 408, 429 and\n * 5xx. A rejected e-CF (4xx) must never be blindly re-sent.\n */\nexport const isRetryableError = (error: unknown): boolean => {\n if (error instanceof DgiiError) {\n return error.retryable;\n }\n if (error instanceof Error) {\n const name = error.name.toLowerCase();\n const message = error.message.toLowerCase();\n return (\n name === 'typeerror' ||\n name === 'aborterror' ||\n name === 'fetcherror' ||\n name === 'timeouterror' ||\n name.includes('cancel') ||\n message.includes('timeout') ||\n message.includes('aborted') ||\n message.includes('network')\n );\n }\n return false;\n};\n\nexport interface ResiliencePolicies {\n readonly retry: IPolicy;\n readonly circuitBreaker: IPolicy;\n readonly timeout: IPolicy;\n readonly bulkhead: IPolicy;\n /** Composed policy: `retry → circuitBreaker → timeout → bulkhead`. */\n readonly policy: IPolicy;\n}\n\n/** Build the composed resilience policy used by the HTTP client. */\nexport const createResiliencePolicies = (\n options: ResilienceOptions = {},\n): ResiliencePolicies => {\n const opts = { ...defaultResilienceOptions, ...options };\n\n const retryPolicy = retry(handleWhen(isRetryableError), {\n maxAttempts: opts.maxRetries,\n backoff: new ExponentialBackoff({ initialDelay: opts.retryInitialDelayMs }),\n });\n\n const breakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: opts.halfOpenAfterMs,\n breaker: new ConsecutiveBreaker(opts.breakerThreshold),\n });\n\n const timeoutPolicy = timeout(opts.timeoutMs, TimeoutStrategy.Aggressive);\n const bulkheadPolicy = bulkhead(opts.bulkheadLimit, opts.bulkheadQueue);\n\n const policy = wrap(\n retryPolicy,\n breakerPolicy,\n timeoutPolicy,\n bulkheadPolicy,\n );\n\n return {\n retry: retryPolicy,\n circuitBreaker: breakerPolicy,\n timeout: timeoutPolicy,\n bulkhead: bulkheadPolicy,\n policy,\n };\n};\n","import { err, ok, type Result } from './result.js';\nimport { DgiiError, extractDgiiErrorMessage, toDgiiError } from './errors.js';\nimport {\n createResiliencePolicies,\n type ResilienceOptions,\n type ResiliencePolicies,\n} from './resilience.js';\n\n/**\n * Pluggable idempotency store. Provide a Redis/Postgres-backed implementation\n * in production so a retried or duplicated submission never double-issues.\n */\nexport interface IdempotencyStore {\n get<T>(key: string): Promise<T | undefined>;\n set<T>(key: string, value: T): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Process-local default. Fine for single-instance usage and tests. */\nexport class InMemoryIdempotencyStore implements IdempotencyStore {\n private readonly store = new Map<string, unknown>();\n\n async get<T>(key: string): Promise<T | undefined> {\n return this.store.get(key) as T | undefined;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.store.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token?: string;\n resilience?: ResilienceOptions;\n policies?: ResiliencePolicies;\n timeoutMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST';\n /** Absolute URL when `absoluteUrl` is true, otherwise a path appended to baseUrl. */\n path: string;\n absoluteUrl?: boolean;\n headers?: Record<string, string>;\n body?: BodyInit;\n query?: Record<string, string | number | undefined>;\n resource?: string;\n}\n\ninterface RequestContext {\n method: string;\n resource: string;\n baseURL: string;\n}\n\n/** Thin HTTP client over the native `fetch`, wrapped in resilience policies. */\nexport class HttpClient {\n private token?: string;\n private readonly policies: ResiliencePolicies;\n private readonly fetchImpl: typeof fetch;\n private readonly baseUrl: string;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.token = options.token;\n this.policies =\n options.policies ??\n createResiliencePolicies({\n ...options.resilience,\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n });\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n setToken(token: string): void {\n this.token = token;\n }\n\n clearToken(): void {\n this.token = undefined;\n }\n\n private buildUrl(\n path: string,\n absoluteUrl: boolean | undefined,\n query: RequestOptions['query'],\n ): string {\n let url = absoluteUrl\n ? path\n : `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;\n\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== '') {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) {\n url += (url.includes('?') ? '&' : '?') + qs;\n }\n }\n return url;\n }\n\n private authHeaders(extra?: Record<string, string>): Record<string, string> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (this.token) {\n headers.Authorization = `Bearer ${this.token}`;\n }\n return { ...headers, ...extra };\n }\n\n private async readBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? '';\n try {\n if (contentType.includes('json')) {\n return await response.json();\n }\n const text = await response.text();\n return text.length ? text : undefined;\n } catch {\n return undefined;\n }\n }\n\n private async parseResponse<T>(\n response: Response,\n ctx: RequestContext,\n ): Promise<Result<T, DgiiError>> {\n const data = await this.readBody(response);\n\n if (response.ok) {\n return ok(data as T);\n }\n\n const message =\n extractDgiiErrorMessage(data) ??\n `DGII request failed with status ${response.status}`;\n const error = new DgiiError(message, {\n code: response.status === 401 ? 'AUTH' : 'HTTP',\n status: response.status,\n statusText: response.statusText,\n resource: ctx.resource,\n method: ctx.method,\n baseURL: ctx.baseURL,\n data,\n });\n\n // Throw retryable failures so the retry/breaker policies can act on them;\n // non-retryable client errors are returned as a typed failure.\n if (error.retryable) {\n throw error;\n }\n return err(error);\n }\n\n async request<T>(options: RequestOptions): Promise<Result<T, DgiiError>> {\n const url = this.buildUrl(options.path, options.absoluteUrl, options.query);\n const method = options.method ?? 'GET';\n const headers = this.authHeaders(options.headers);\n const ctx: RequestContext = {\n method,\n resource: options.resource ?? options.path,\n baseURL: this.baseUrl,\n };\n\n try {\n return await this.policies.policy.execute(async ({ signal }) => {\n const response = await this.fetchImpl(url, {\n method,\n headers,\n body: options.body,\n signal,\n });\n return this.parseResponse<T>(response, ctx);\n });\n } catch (error) {\n return err(toDgiiError(error, ctx));\n }\n }\n\n get<T>(\n path: string,\n query?: RequestOptions['query'],\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n return this.request<T>({\n method: 'GET',\n path,\n query,\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n\n /**\n * POST a signed XML as a multipart `xml` file part. The runtime computes\n * `Content-Length` from the Blob — never set it manually.\n */\n postMultipart<T>(\n path: string,\n fileName: string,\n xml: string,\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n const form = new FormData();\n form.append('xml', new Blob([xml], { type: 'application/xml' }), fileName);\n return this.request<T>({\n method: 'POST',\n path,\n body: form,\n headers: { Accept: 'application/json' },\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n}\n","import { readFileSync } from 'node:fs';\nimport forge from 'node-forge';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport interface P12ReaderData {\n key?: string;\n cert?: string;\n publicKey?: string;\n}\n\nexport interface CertificateInfo {\n subject: string;\n issuer: string;\n validFrom: Date;\n validTo: Date;\n serialNumber: string;\n}\n\nconst asErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\n/** Reads a PKCS#12 (.p12) bundle and extracts the private key + certificate. */\nexport class P12Reader {\n constructor(private readonly passphrase: string) {}\n\n private load(base64: string): forge.pkcs12.Pkcs12Pfx {\n const der = forge.util.decode64(base64);\n const asn1 = forge.asn1.fromDer(der);\n return forge.pkcs12.pkcs12FromAsn1(asn1, false, this.passphrase);\n }\n\n private extractKey(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n const keyBags = p12.getBags({\n bagType: forge.pki.oids.pkcs8ShroudedKeyBag,\n });\n const pkcs8Key = keyBags[forge.pki.oids.pkcs8ShroudedKeyBag]?.[0];\n if (pkcs8Key?.key) {\n return forge.pki.privateKeyToPem(pkcs8Key.key);\n }\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });\n const certBag = certBags[forge.pki.oids.certBag]?.[0];\n if (certBag?.key) {\n return forge.pki.privateKeyToPem(certBag.key);\n }\n return undefined;\n }\n\n private extractCertificate(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });\n const certBag = certBags[forge.pki.oids.certBag]?.[0];\n if (!certBag?.cert) {\n return undefined;\n }\n return forge.pki.certificateToPem(certBag.cert);\n }\n\n getKeyFromFile(fileName: string): Result<P12ReaderData, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getKeyFromStringBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getKeyFromStringBase64(base64: string): Result<P12ReaderData, DgiiError> {\n try {\n const p12 = this.load(base64);\n const key = this.extractKey(p12);\n const cert = this.extractCertificate(p12);\n if (!key || !cert) {\n return err(\n new DgiiError('PKCS#12 must contain a private key and certificate', {\n code: 'CERTIFICATE',\n }),\n );\n }\n const publicKey = forge.pki.publicKeyToPem(\n forge.pki.certificateFromPem(cert).publicKey,\n );\n return ok({ key, cert, publicKey });\n } catch (error) {\n return err(\n new DgiiError(`Unable to parse .p12: ${asErrorMessage(error)}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n private toCertificateInfo(certPem: string): CertificateInfo {\n const certificate = forge.pki.certificateFromPem(certPem);\n return {\n subject: certificate.subject.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n issuer: certificate.issuer.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n validFrom: certificate.validity.notBefore,\n validTo: certificate.validity.notAfter,\n serialNumber: certificate.serialNumber,\n };\n }\n\n getCertificateInfo(fileName: string): Result<CertificateInfo, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getCertificateInfoFromBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getCertificateInfoFromBase64(\n base64: string,\n ): Result<CertificateInfo, DgiiError> {\n try {\n const certPem = this.extractCertificate(this.load(base64));\n if (!certPem) {\n return err(\n new DgiiError('Certificate not found in PKCS#12', {\n code: 'CERTIFICATE',\n }),\n );\n }\n return ok(this.toCertificateInfo(certPem));\n } catch (error) {\n return err(\n new DgiiError(\n `Unable to extract certificate info: ${asErrorMessage(error)}`,\n { code: 'CERTIFICATE', cause: error },\n ),\n );\n }\n }\n}\n","import crypto from 'node:crypto';\nimport { DOMParser } from '@xmldom/xmldom';\nimport { C14nCanonicalization, SignedXml } from 'xml-crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport type DgiiDocumentType =\n 'SemillaModel' | 'ECF' | 'RFCE' | 'ARECF' | 'ACECF' | 'ANECF' | (string & {});\n\nconst C14N_INCLUSIVE = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';\nconst RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';\nconst SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';\nconst ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature';\n/**\n * Custom digest URI: DGII hashes the inclusive C14N 1.0 form of the referenced\n * document. xml-crypto's built-in SHA-256 hashes its raw serialization, so we\n * register a digest backed by xml-crypto's inclusive C14N implementation.\n */\nconst CUSTOM_DIGEST_URI = 'http://dgii.gov.do/digest/sha256-c14n';\n\ninterface XmldomDocument extends Document {\n childNodes: NodeListOf<ChildNode>;\n}\n\n/**\n * DGII-compatible digest: hash the inclusive C14N 1.0 form of the referenced\n * document — the exact bytes a .NET/DGII verifier computes.\n */\nclass DgiiDigest {\n getHash(xml: string): string {\n const doc = new DOMParser().parseFromString(\n xml,\n ) as unknown as XmldomDocument;\n const canonical = new C14nCanonicalization().process(\n doc as unknown as Node,\n {},\n );\n return crypto\n .createHash('sha256')\n .update(canonical, 'utf8')\n .digest('base64');\n }\n\n getAlgorithmName(): string {\n return SHA256;\n }\n}\n\ninterface StrictParseResult {\n doc: XmldomDocument;\n rootName: string;\n}\n\nconst parseStrict = (xml: string): StrictParseResult => {\n const errors: string[] = [];\n const doc = new DOMParser({\n errorHandler: {\n warning: () => undefined,\n error: (message: string) => errors.push(message),\n fatalError: (message: string) => errors.push(message),\n },\n }).parseFromString(xml, 'text/xml') as unknown as XmldomDocument;\n\n if (errors.length) {\n throw new Error(`Invalid XML: ${errors.join('; ')}`);\n }\n const root = doc.documentElement;\n if (!root) {\n throw new Error('Unable to parse XML or find root element');\n }\n if (root.nodeName === 'parsererror' || root.localName === 'parsererror') {\n throw new Error(`Invalid XML: ${root.textContent ?? 'parse error'}`);\n }\n return {\n doc,\n rootName: root.localName ?? root.nodeName,\n };\n};\n\n/** Remove whitespace-only text nodes and comments before canonicalization. */\nconst cleanNodes = (node: Node): void => {\n for (let index = 0; index < node.childNodes.length; index += 1) {\n const child = node.childNodes[index];\n if (!child) {\n continue;\n }\n const isComment = child.nodeType === 8;\n const isWhitespace =\n child.nodeType === 3 && !/\\S/.test(child.nodeValue ?? '');\n if (isComment || isWhitespace) {\n node.removeChild(child);\n index -= 1;\n } else if (child.nodeType === 1) {\n cleanNodes(child);\n }\n }\n};\n\n/** Signs DGII XML documents with XMLDSig (enveloped, inclusive C14N, RSA-SHA256). */\nexport class Signature {\n constructor(\n private readonly privateKey: string,\n private readonly certificatePem: string,\n ) {}\n\n signXml(\n xml: string,\n rootElName?: DgiiDocumentType,\n ): Result<string, DgiiError> {\n try {\n const { doc, rootName } = parseStrict(xml);\n const elementName = rootElName ?? rootName;\n\n const sig = new SignedXml({\n privateKey: this.privateKey,\n publicCert: this.certificatePem,\n signatureAlgorithm: RSA_SHA256,\n canonicalizationAlgorithm: C14N_INCLUSIVE,\n });\n\n const hashAlgorithms = (\n sig as unknown as {\n HashAlgorithms: Record<string, unknown>;\n }\n ).HashAlgorithms;\n hashAlgorithms[CUSTOM_DIGEST_URI] = DgiiDigest;\n\n sig.addReference({\n xpath: `//*[local-name(.)='${elementName}']`,\n transforms: [ENVELOPED],\n digestAlgorithm: CUSTOM_DIGEST_URI,\n isEmptyUri: true,\n } as unknown as Parameters<SignedXml['addReference']>[0]);\n\n cleanNodes(doc as unknown as Node);\n sig.computeSignature(doc.toString());\n return ok(sig.getSignedXml());\n } catch (error) {\n return err(\n new DgiiError(\n `Failed to sign XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'SIGNING', cause: error },\n ),\n );\n }\n }\n}\n\nexport interface XmlCertificateValidation {\n isValid: boolean;\n subject?: string;\n issuer?: string;\n validFrom?: string;\n validTo?: string;\n error?: string;\n}\n\n/** Validate the embedded X509 certificate of a signed XML document. */\nexport const validateXMLCertificate = (\n xml: string,\n): XmlCertificateValidation => {\n try {\n const match = xml.match(/<X509Certificate>([\\s\\S]*?)<\\/X509Certificate>/);\n if (!match?.[1]) {\n return { isValid: false, error: 'X509Certificate not found' };\n }\n const der = Buffer.from(match[1].replace(/\\s+/g, ''), 'base64');\n const certificate = new crypto.X509Certificate(der);\n const notBefore = new Date(certificate.validFrom).getTime();\n const notAfter = new Date(certificate.validTo).getTime();\n const now = Date.now();\n const isValid = now >= notBefore && now <= notAfter;\n return {\n isValid,\n subject: certificate.subject,\n issuer: certificate.issuer,\n validFrom: certificate.validFrom,\n validTo: certificate.validTo,\n error: isValid ? undefined : 'Certificate expired or not yet valid',\n };\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n};\n","import convert from 'xml-js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\n/**\n * Converts between the DGII XML documents and the \"compact\" JSON shape used by\n * `xml-js` (a dict key is an element, an array is a repeated element, and\n * `_attributes` / `_text` carry attributes and text).\n */\nexport class Transformer {\n json2xml(dataObject: object, round = false): Result<string, DgiiError> {\n try {\n const data: Record<string, unknown> = {\n _declaration: { _attributes: { version: '1.0', encoding: 'utf-8' } },\n ...dataObject,\n };\n\n const xml = convert.js2xml(data as convert.ElementCompact, {\n compact: true,\n ignoreComment: true,\n spaces: 2,\n fullTagEmptyElement: true,\n textFn: (value: string, label: string) => {\n const omits = ['version'];\n if (\n /^\\d+\\.\\d+$/.test(value) &&\n round &&\n !omits.includes(label.toLowerCase())\n ) {\n return parseFloat(value).toFixed(2);\n }\n return value;\n },\n });\n\n return ok(xml);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting JSON to XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n\n xml2json<T>(xml: string): Result<T, DgiiError> {\n try {\n const json = convert.xml2js(xml, {\n compact: true,\n ignoreComment: true,\n nativeType: false,\n });\n return ok(json as T);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting XML to JSON: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n}\n","import { BaseUrl, Environment } from './environment.js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport { Transformer } from './transformer.js';\n\n/** First 6 chars of the `<SignatureValue>` (DGII security code). */\nexport const getCodeSixDigitfromSignature = (\n signedXml: string,\n): Result<string, DgiiError> => {\n const match = signedXml.match(/<SignatureValue>([\\s\\S]*?)<\\/SignatureValue>/);\n const value = match?.[1]?.trim();\n if (!value) {\n return err(new DgiiError('SignatureValue not found', { code: 'SIGNING' }));\n }\n if (value.length < 6) {\n return err(\n new DgiiError('SignatureValue is too short', { code: 'SIGNING' }),\n );\n }\n return ok(value.slice(0, 6));\n};\n\n/** QR URL for a factura de consumo (FC). */\nexport const generateFcQRCodeURL = (\n rncemisor: string,\n encf: string,\n montototal: number,\n codigoseguridad: string,\n env: Environment,\n): string =>\n `${BaseUrl.CF}/${env.toLowerCase()}/consultatimbrefc?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&encf=${encodeURIComponent(encf)}&montototal=${encodeURIComponent(\n String(montototal),\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n\n/** QR URL for a crédito fiscal (e-CF). */\nexport const generateEcfQRCodeURL = (\n rncemisor: string,\n rncComprador: string,\n encf: string,\n montototal: string,\n fechaEmision: string,\n fechaFirma: string,\n codigoseguridad: string,\n env: Environment,\n): string => {\n let rncCompradorParam = '';\n if (rncComprador && !/E43/i.test(encf) && !/E47/i.test(encf)) {\n rncCompradorParam = `RncComprador=${encodeURIComponent(rncComprador)}&`;\n }\n return `${BaseUrl.ECF}/${env.toLowerCase()}/consultatimbre?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&${rncCompradorParam}encf=${encodeURIComponent(\n encf,\n )}&fechaemision=${encodeURIComponent(\n fechaEmision,\n )}&montototal=${encodeURIComponent(\n montototal,\n )}&fechafirma=${encodeURIComponent(\n fechaFirma,\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n};\n\nconst formatInSantoDomingo = (date: Date, withTime: boolean): string => {\n const parts = new Intl.DateTimeFormat('es-DO', {\n timeZone: 'America/Santo_Domingo',\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n ...(withTime\n ? { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }\n : {}),\n })\n .formatToParts(date)\n .reduce<Record<string, string>>((acc, part) => {\n acc[part.type] = part.value;\n return acc;\n }, {});\n\n const datePart = `${parts.day}-${parts.month}-${parts.year}`;\n return withTime\n ? `${datePart} ${parts.hour}:${parts.minute}:${parts.second}`\n : datePart;\n};\n\n/** `DD-MM-YYYY HH:mm:ss` in America/Santo_Domingo. */\nexport const getCurrentFormattedDateTime = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, true);\n\n/** `DD-MM-YYYY` in America/Santo_Domingo. */\nexport const getCurrentFormattedDate = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, false);\n\n/** Extract the XML payload embedded in a DGII commercial-approval body. */\nexport const getXmlFromBodyResponse = (\n body: string,\n lastTagName = 'ACECF',\n): string | undefined =>\n body.match(new RegExp(`<\\\\?xml[\\\\s\\\\S]*?<\\\\/${lastTagName}>`))?.[0];\n\ninterface CompactElement {\n _text?: string;\n [key: string]: unknown;\n}\n\ninterface ImpuestoAdicional {\n TipoImpuesto?: CompactElement;\n MontoImpuestoSelectivoConsumoEspecifico?: CompactElement;\n MontoImpuestoSelectivoConsumoAdvalorem?: CompactElement;\n OtrosImpuestosAdicionales?: CompactElement;\n}\n\ninterface EcfTotales {\n MontoGravadoTotal?: CompactElement;\n MontoGravadoI1?: CompactElement;\n MontoGravadoI2?: CompactElement;\n MontoGravadoI3?: CompactElement;\n MontoExento?: CompactElement;\n TotalITBIS?: CompactElement;\n TotalITBIS1?: CompactElement;\n TotalITBIS2?: CompactElement;\n TotalITBIS3?: CompactElement;\n MontoImpuestoAdicional?: CompactElement;\n ImpuestosAdicionales?: {\n ImpuestoAdicional?: ImpuestoAdicional | ImpuestoAdicional[];\n };\n MontoTotal?: CompactElement;\n MontoNoFacturable?: CompactElement;\n MontoPeriodo?: CompactElement;\n}\n\ninterface EcfJson {\n ECF: {\n Encabezado?: {\n Version?: CompactElement;\n IdDoc?: {\n TipoeCF?: CompactElement;\n eNCF?: CompactElement;\n TipoIngresos?: CompactElement;\n TipoPago?: CompactElement;\n TablaFormasPago?: CompactElement;\n };\n Emisor?: {\n RNCEmisor?: CompactElement;\n RazonSocialEmisor?: CompactElement;\n FechaEmision?: CompactElement;\n };\n Comprador?: {\n RNCComprador?: CompactElement;\n IdentificadorExtranjero?: CompactElement;\n RazonSocialComprador?: CompactElement;\n };\n Totales?: EcfTotales;\n };\n };\n}\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (value === undefined || value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n};\n\nconst isEmptyObject = (value: unknown): boolean =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value as Record<string, unknown>).length === 0;\n\nconst removeEmptyValues = (input: unknown): unknown => {\n if (input === null || input === undefined || input === '') {\n return undefined;\n }\n if (Array.isArray(input)) {\n const filtered = input\n .map(removeEmptyValues)\n .filter(\n (item) =>\n item !== null &&\n item !== undefined &&\n item !== '' &&\n !isEmptyObject(item),\n );\n return filtered.length ? filtered : undefined;\n }\n if (typeof input === 'object') {\n const output: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(\n input as Record<string, unknown>,\n )) {\n const cleaned = removeEmptyValues(value);\n if (cleaned !== undefined && cleaned !== '' && !isEmptyObject(cleaned)) {\n output[key] = cleaned;\n }\n }\n return Object.keys(output).length ? output : undefined;\n }\n return input;\n};\n\n/**\n * Build the RFCE (summary invoice) document from a signed ECF-32 document.\n * Returns the unsigned RFCE XML plus the 6-digit security code.\n */\nexport const convertECF32ToRFCE = (\n ecf32Xml: string,\n): Result<{ xml: string; securityCode: string }, DgiiError> => {\n const securityCode = getCodeSixDigitfromSignature(ecf32Xml);\n if (securityCode.isErr()) {\n return err(securityCode.error);\n }\n\n const transformer = new Transformer();\n const parsed = transformer.xml2json<EcfJson>(ecf32Xml);\n if (parsed.isErr()) {\n return err(parsed.error);\n }\n\n const encabezado = parsed.value.ECF.Encabezado;\n const impuestos = toArray(\n encabezado?.Totales?.ImpuestosAdicionales?.ImpuestoAdicional,\n );\n\n const rfce = removeEmptyValues({\n RFCE: {\n Encabezado: {\n Version: encabezado?.Version,\n IdDoc: {\n TipoeCF: encabezado?.IdDoc?.TipoeCF,\n eNCF: encabezado?.IdDoc?.eNCF,\n TipoIngresos: encabezado?.IdDoc?.TipoIngresos,\n TipoPago: encabezado?.IdDoc?.TipoPago,\n TablaFormasPago: encabezado?.IdDoc?.TablaFormasPago,\n },\n Emisor: {\n RNCEmisor: encabezado?.Emisor?.RNCEmisor,\n RazonSocialEmisor: encabezado?.Emisor?.RazonSocialEmisor,\n FechaEmision: encabezado?.Emisor?.FechaEmision,\n },\n Comprador: {\n RNCComprador: encabezado?.Comprador?.RNCComprador,\n IdentificadorExtranjero:\n encabezado?.Comprador?.IdentificadorExtranjero,\n RazonSocialComprador: encabezado?.Comprador?.RazonSocialComprador,\n },\n Totales: {\n MontoGravadoTotal: encabezado?.Totales?.MontoGravadoTotal,\n MontoGravadoI1: encabezado?.Totales?.MontoGravadoI1,\n MontoGravadoI2: encabezado?.Totales?.MontoGravadoI2,\n MontoGravadoI3: encabezado?.Totales?.MontoGravadoI3,\n MontoExento: encabezado?.Totales?.MontoExento,\n TotalITBIS: encabezado?.Totales?.TotalITBIS,\n TotalITBIS1: encabezado?.Totales?.TotalITBIS1,\n TotalITBIS2: encabezado?.Totales?.TotalITBIS2,\n TotalITBIS3: encabezado?.Totales?.TotalITBIS3,\n MontoImpuestoAdicional: encabezado?.Totales?.MontoImpuestoAdicional,\n ImpuestosAdicionales: {\n ImpuestoAdicional: impuestos.map((impuesto) => ({\n TipoImpuesto: impuesto.TipoImpuesto,\n MontoImpuestoSelectivoConsumoEspecifico:\n impuesto.MontoImpuestoSelectivoConsumoEspecifico,\n MontoImpuestoSelectivoConsumoAdvalorem:\n impuesto.MontoImpuestoSelectivoConsumoAdvalorem,\n OtrosImpuestosAdicionales: impuesto.OtrosImpuestosAdicionales,\n })),\n },\n MontoTotal: encabezado?.Totales?.MontoTotal,\n MontoNoFacturable: encabezado?.Totales?.MontoNoFacturable,\n MontoPeriodo: encabezado?.Totales?.MontoPeriodo,\n },\n CodigoSeguridadeCF: securityCode.value,\n },\n },\n });\n\n if (typeof rfce !== 'object' || rfce === null) {\n return err(\n new DgiiError('Unable to build RFCE document', { code: 'VALIDATION' }),\n );\n }\n\n const xml = transformer.json2xml(rfce);\n if (xml.isErr()) {\n return err(xml.error);\n }\n\n return ok({ xml: xml.value, securityCode: securityCode.value });\n};\n","import { createHash } from 'node:crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport {\n BaseUrl,\n Endpoint,\n Environment,\n SenderReceiverEndpoint,\n buildSenderReceiverUrl,\n buildUrl,\n} from './environment.js';\nimport {\n HttpClient,\n InMemoryIdempotencyStore,\n type IdempotencyStore,\n} from './http.js';\nimport type { ResilienceOptions } from './resilience.js';\nimport { Signature } from './signing.js';\nimport type { P12ReaderData } from './certificate.js';\nimport type {\n AuthToken,\n CommercialApprovalResponse,\n InquiryInvoiceSummary,\n InquiryStatusResponse,\n InvoiceResponse,\n InvoiceSummaryResponse,\n ServiceDirectoryResponse,\n SummaryTrackingStatusResponse,\n TrackingStatusResponse,\n VoidNCFResponse,\n} from './types.js';\n\nexport interface EcfOptions {\n /** Pre-existing bearer token (skips the authentication round-trip). */\n token?: string;\n /** Pluggable idempotency store; defaults to an in-memory store. */\n idempotencyStore?: IdempotencyStore;\n resilience?: ResilienceOptions;\n timeoutMs?: number;\n /** Injectable fetch (useful for tests). */\n fetchImpl?: typeof fetch;\n}\n\ninterface PendingSubmission {\n readonly pending: true;\n}\n\nconst PENDING_SUBMISSION: PendingSubmission = { pending: true };\n\nconst isPendingSubmission = (value: unknown): value is PendingSubmission =>\n typeof value === 'object' &&\n value !== null &&\n (value as { pending?: unknown }).pending === true;\n\nconst sha256Hex = (value: string): string =>\n createHash('sha256').update(value, 'utf8').digest('hex');\n\nconst extractTag = (xml: string, tag: string): string | undefined => {\n const match = xml.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));\n return match?.[1]?.trim();\n};\n\n/**\n * DGII e-CF client. Every method returns a `Result` — no thrown domain errors.\n */\nexport class ECF {\n private readonly environment: Environment;\n private readonly http: HttpClient;\n private readonly idempotency: IdempotencyStore;\n private readonly credentials: P12ReaderData;\n private readonly inFlight = new Map<\n string,\n Promise<Result<unknown, DgiiError>>\n >();\n\n constructor(\n credentials: P12ReaderData,\n environment: Environment = Environment.Dev,\n options: EcfOptions = {},\n ) {\n this.credentials = credentials;\n this.environment = environment;\n this.idempotency =\n options.idempotencyStore ?? new InMemoryIdempotencyStore();\n this.http = new HttpClient({\n baseUrl: BaseUrl.ECF,\n ...(options.token !== undefined ? { token: options.token } : {}),\n ...(options.resilience !== undefined\n ? { resilience: options.resilience }\n : {}),\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n ...(options.fetchImpl !== undefined\n ? { fetchImpl: options.fetchImpl }\n : {}),\n });\n }\n\n private buildIdempotencyKey(signedXml: string): string {\n const rnc = extractTag(signedXml, 'RNCEmisor') ?? 'unknown-rnc';\n const encf = extractTag(signedXml, 'eNCF') ?? 'unknown-encf';\n return `${rnc}:${encf}:${sha256Hex(signedXml)}`;\n }\n\n private async singleFlight<T>(\n key: string,\n task: () => Promise<Result<T, DgiiError>>,\n ): Promise<Result<T, DgiiError>> {\n const existing = this.inFlight.get(key);\n if (existing) {\n return existing as Promise<Result<T, DgiiError>>;\n }\n const promise = task();\n this.inFlight.set(key, promise as Promise<Result<unknown, DgiiError>>);\n try {\n return await promise;\n } finally {\n this.inFlight.delete(key);\n }\n }\n\n /** Authenticate against DGII (or a buyer host) and store the bearer token. */\n async authenticate(\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const seed = await this.getSeed(buyerHost);\n if (seed.isErr()) {\n return err(seed.error);\n }\n if (\n typeof this.credentials.key !== 'string' ||\n typeof this.credentials.cert !== 'string'\n ) {\n return err(\n new DgiiError(\n 'A private key and certificate PEM are required to authenticate',\n { code: 'CERTIFICATE' },\n ),\n );\n }\n\n const signed = new Signature(\n this.credentials.key,\n this.credentials.cert,\n ).signXml(seed.value, 'SemillaModel');\n if (signed.isErr()) {\n return err(signed.error);\n }\n\n const token = await this.getAuthToken(signed.value, buyerHost);\n if (token.isErr()) {\n return err(token.error);\n }\n this.http.setToken(token.value.token);\n return ok(token.value);\n }\n\n private getSeed(buyerHost?: string): Promise<Result<string, DgiiError>> {\n if (buyerHost) {\n const url = buildSenderReceiverUrl(\n buyerHost,\n SenderReceiverEndpoint.Seed,\n );\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: SenderReceiverEndpoint.Seed,\n });\n }\n const url = buildUrl(this.environment, Endpoint.Seed);\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: Endpoint.Seed,\n });\n }\n\n private getAuthToken(\n signedSeed: string,\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.ValidateSeed)\n : buildUrl(this.environment, Endpoint.ValidateSeed);\n return this.http.postMultipart<AuthToken>(url, 'signed.xml', signedSeed, {\n absoluteUrl: true,\n resource: Endpoint.ValidateSeed,\n });\n }\n\n /**\n * Submit a signed e-CF. Idempotent on `RNC + eNCF + SHA-256(signed XML)`:\n * a repeated call returns the cached response instead of double-issuing.\n */\n async sendElectronicDocument(\n signedXml: string,\n fileName: string,\n buyerHost?: string,\n ): Promise<Result<InvoiceResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit: record the pending submission before the\n // network call so an interrupted send can be reconciled, not re-issued.\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.SendInvoice)\n : buildUrl(this.environment, Endpoint.SendInvoice);\n const result = await this.http.postMultipart<InvoiceResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendInvoice },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n /** Submit a signed summary invoice (RFCE). Idempotent like submissions. */\n async sendSummary(\n signedXml: string,\n fileName: string,\n ): Promise<Result<InvoiceSummaryResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceSummaryResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit (see sendElectronicDocument).\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buildUrl(this.environment, Endpoint.SendSummary, BaseUrl.CF);\n const result = await this.http.postMultipart<InvoiceSummaryResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendSummary },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n statusTrackId(\n trackId: string,\n ): Promise<Result<TrackingStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.TrackResultStatus);\n return this.http.get<TrackingStatusResponse>(\n url,\n { trackId },\n { absoluteUrl: true, resource: Endpoint.TrackResultStatus },\n );\n }\n\n inquiryStatus(\n rncEmisor: string,\n ncfElectronico: string,\n rncComprador?: string,\n codigoSeguridad?: string,\n ): Promise<Result<InquiryStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.InquiryStatus);\n return this.http.get<InquiryStatusResponse>(\n url,\n { rncEmisor, ncfElectronico, rncComprador, codigoSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryStatus },\n );\n }\n\n trackStatuses(\n rncEmisor: string,\n encf: string,\n ): Promise<Result<SummaryTrackingStatusResponse[], DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.AllTrackingEcf);\n return this.http.get<SummaryTrackingStatusResponse[]>(\n url,\n { rncEmisor, encf },\n { absoluteUrl: true, resource: Endpoint.AllTrackingEcf },\n );\n }\n\n /** Normalizes DGII's inconsistent (array | single object) directory payload. */\n async getCustomerDirectory(\n rnc: string,\n ): Promise<Result<ServiceDirectoryResponse[] | undefined, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Directory);\n const result = await this.http.get<\n ServiceDirectoryResponse[] | ServiceDirectoryResponse\n >(url, { rnc }, { absoluteUrl: true, resource: Endpoint.Directory });\n if (result.isErr()) {\n return err(result.error);\n }\n const data = result.value;\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n return ok(Array.isArray(data) ? data : [data]);\n }\n\n /** RFCE inquiry — DGII production only. */\n getSummaryInvoiceInquiry(\n rnc: string,\n encf: string,\n codSeguridad: string,\n ): Promise<Result<InquiryInvoiceSummary, DgiiError>> {\n const url = buildUrl(\n this.environment,\n Endpoint.InquiryInvoiceSummary,\n BaseUrl.CF,\n );\n return this.http.get<InquiryInvoiceSummary>(\n url,\n { rnc_emisor: rnc, encf, cod_seguridad_eCF: codSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryInvoiceSummary },\n );\n }\n\n sendCommercialApproval(\n signedXml: string,\n fileName: string,\n ): Promise<Result<CommercialApprovalResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.CommercialApproval);\n return this.http.postMultipart<CommercialApprovalResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.CommercialApproval },\n );\n }\n\n voidENCF(\n signedXml: string,\n fileName: string,\n ): Promise<Result<VoidNCFResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Void);\n return this.http.postMultipart<VoidNCFResponse>(url, fileName, signedXml, {\n absoluteUrl: true,\n resource: Endpoint.Void,\n });\n }\n}\n"],"mappings":"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","names":["Environment","Endpoint","SenderReceiverEndpoint","TrackStatusEnum","err","forge","crypto","convert","import_node_crypto","url"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/environment.ts","../src/types.ts","../src/errors.ts","../src/result.ts","../src/resilience.ts","../src/http.ts","../src/certificate.ts","../src/signing.ts","../src/transformer.ts","../src/utils.ts","../src/client.ts"],"sourcesContent":["export * from './environment.js';\nexport * from './types.js';\nexport * from './errors.js';\nexport * from './result.js';\nexport * from './resilience.js';\nexport * from './http.js';\nexport * from './certificate.js';\nexport * from './signing.js';\nexport * from './transformer.js';\nexport * from './utils.js';\nexport * from './client.js';\n","export enum Environment {\n /** DGII test environment */\n Dev = 'TesteCF',\n /** DGII certification environment */\n Cert = 'CerteCF',\n /** DGII production environment */\n Prod = 'eCF',\n}\n\nexport const BaseUrl = {\n /** Crédito fiscal / general e-CF services */\n ECF: 'https://ecf.dgii.gov.do',\n /** Factura de consumo (< DOP 250,000) */\n CF: 'https://fc.dgii.gov.do',\n /** DGII service status */\n STATUS: 'https://statusecf.dgii.gov.do',\n} as const;\n\nexport type BaseUrlKey = keyof typeof BaseUrl;\n\nexport enum Endpoint {\n Seed = 'Autenticacion/api/Autenticacion/Semilla',\n ValidateSeed = 'autenticacion/api/Autenticacion/ValidarSemilla',\n SendInvoice = 'recepcion/api/FacturasElectronicas',\n SendSummary = 'recepcionfc/api/recepcion/ecf',\n InquiryInvoiceSummary = 'consultarfce/api/Consultas/Consulta',\n CommercialApproval = 'aprobacionComercial/api/AprobacionComercial',\n TrackResultStatus = 'consultaresultado/api/Consultas/Estado',\n InquiryStatus = 'consultaestado/api/Consultas/Estado',\n AllTrackingEcf = 'ConsultaTrackIds/api/TrackIds/Consulta',\n Directory = 'consultadirectorio/api/consultas/obtenerdirectorioporrnc',\n Void = 'anulacionrangos/api/operaciones/anularrango',\n}\n\n/** Endpoints used when talking to a buyer's Sender↔Receiver host. */\nexport enum SenderReceiverEndpoint {\n Seed = 'fe/autenticacion/api/semilla',\n ValidateSeed = 'fe/autenticacion/api/validacioncertificado',\n SendInvoice = 'fe/recepcion/api/ecf',\n CommercialApproval = 'fe/aprobacioncomercial/api/ecf',\n}\n\n/** Build an absolute DGII URL: `${baseUrl}/${environment}/${endpoint}`. */\nexport const buildUrl = (\n environment: Environment,\n endpoint: Endpoint,\n baseUrl: string = BaseUrl.ECF,\n): string => `${baseUrl.replace(/\\/+$/, '')}/${environment}/${endpoint}`;\n\n/** Build an absolute Sender↔Receiver URL against a buyer host. */\nexport const buildSenderReceiverUrl = (\n host: string,\n endpoint: SenderReceiverEndpoint,\n): string => `${host.replace(/\\/+$/, '')}/${endpoint}`;\n","export interface Mensaje {\n valor: string;\n codigo: number;\n}\n\nexport interface AuthToken {\n token: string;\n expira: string;\n expedido: string;\n}\n\nexport enum TrackStatusEnum {\n NotFound = 'No encontrado',\n Accepted = 'Aceptado',\n Rejected = 'Rechazado',\n InProcess = 'En Proceso',\n ConditionalAccepted = 'Aceptado Condicional',\n}\n\nexport type TrackStatusCode = 0 | 1 | 2 | 3 | 4;\n\nexport interface TrackingStatusResponse {\n trackId: string;\n codigo: TrackStatusCode;\n estado: TrackStatusEnum;\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n fechaRecepcion: string;\n mensajes?: Mensaje[];\n}\n\nexport type InquiryStatusCode = 0 | 1 | 2;\n\nexport type InquiryStatus = 'No encontrado' | 'Aceptado' | 'Rechazado';\n\nexport interface InquiryStatusResponse {\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n rncEmisor?: string;\n ncfElectronico?: string;\n montoTotal?: number;\n totalITBIS?: number;\n fechaEmision?: string;\n fechaFirma?: string;\n rncComprador?: string;\n codigoSeguridad?: string;\n idExtranjero?: string;\n}\n\nexport interface SummaryTrackingStatusResponse {\n trackId: string;\n estado: string;\n fechaRecepcion: string;\n}\n\nexport interface InvoiceResponse {\n trackId?: string;\n error?: string;\n mensajes?: Mensaje[];\n}\n\nexport interface InvoiceSummaryResponse {\n codigo: number;\n estado: 'Aceptado' | 'Rechazado' | 'Aceptado Condicional';\n mensajes?: Mensaje[];\n encf: string;\n secuenciaUtilizada: boolean;\n}\n\nexport interface ServiceDirectoryResponse {\n nombre: string;\n rnc: string;\n urlRecepcion: string;\n urlAceptacion: string;\n urlOpcional: string;\n}\n\nexport interface InquiryInvoiceSummary {\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n mensajes?: Mensaje[];\n}\n\nexport interface CommercialApprovalResponse {\n codigo: '01' | '02';\n estado: 'Aprobación Comercial Aprobada.' | 'Aprobacion Comercial Rechazada.';\n mensaje: string[];\n}\n\nexport interface VoidNCFResponse {\n rnc: string;\n codigo: string;\n nombre: string;\n mensajes: string[];\n}\n","import type { Mensaje } from './types.js';\n\nexport type DgiiErrorCode =\n | 'INVALID_XML'\n | 'CERTIFICATE'\n | 'SIGNING'\n | 'HTTP'\n | 'AUTH'\n | 'TIMEOUT'\n | 'CIRCUIT_OPEN'\n | 'IDEMPOTENCY'\n | 'VALIDATION'\n | 'UNKNOWN';\n\nconst RETRYABLE_STATUSES = new Set<number>([408, 429, 500, 502, 503, 504]);\n\nexport const isRetryableStatus = (status: number | undefined): boolean =>\n status !== undefined && RETRYABLE_STATUSES.has(status);\n\nexport interface DgiiErrorOptions {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n data?: unknown;\n mensajes?: Mensaje[];\n retryable?: boolean;\n cause?: unknown;\n}\n\nconst MAX_RAW = 1000;\n\nconst truncate = (value: string): string =>\n value.length > MAX_RAW ? `${value.slice(0, MAX_RAW)}…` : value;\n\nconst collapseWhitespace = (value: string): string =>\n value.replace(/\\s+/g, ' ').trim();\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst looksLikeHtml = (value: string): boolean =>\n /^\\s*<(?:!doctype|html|body|head)\\b/i.test(value);\n\nconst stripHtml = (value: string): string =>\n collapseWhitespace(\n value\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<[^>]+>/g, ' '),\n );\n\nconst readMensajes = (value: unknown): Mensaje[] | undefined => {\n if (!Array.isArray(value) || value.length === 0) {\n return undefined;\n }\n const out: Mensaje[] = [];\n for (const item of value) {\n if (typeof item === 'string' && item.trim()) {\n out.push({ valor: item.trim(), codigo: 0 });\n } else if (isObject(item) && typeof item.valor === 'string') {\n out.push({\n valor: item.valor,\n codigo: typeof item.codigo === 'number' ? item.codigo : 0,\n });\n }\n }\n return out.length ? out : undefined;\n};\n\nconst MESSAGE_KEYS = [\n 'mensaje',\n 'Mensaje',\n 'message',\n 'Message',\n 'error',\n 'Error',\n 'errorMessage',\n 'error_description',\n 'detail',\n 'Detail',\n 'title',\n 'Title',\n 'descripcion',\n 'Descripcion',\n];\n\n/**\n * Reduce DGII's inconsistent error payloads (bare string, `{ mensajes }`,\n * ASP.NET ProblemDetails/ModelState, or an HTML page) to a single message.\n */\nexport const extractDgiiErrorMessage = (\n data: unknown,\n seen: WeakSet<object> = new WeakSet<object>(),\n): string | undefined => {\n if (data === undefined || data === null) {\n return undefined;\n }\n\n if (typeof data === 'string') {\n const trimmed = data.trim();\n if (!trimmed) {\n return undefined;\n }\n if (/^[[{\"]/.test(trimmed)) {\n try {\n return extractDgiiErrorMessage(JSON.parse(trimmed), seen);\n } catch {\n // Not JSON after all — fall through to raw text.\n }\n }\n if (looksLikeHtml(trimmed)) {\n const text = stripHtml(trimmed);\n return text ? truncate(text) : undefined;\n }\n return truncate(collapseWhitespace(trimmed));\n }\n\n if (typeof data === 'number' || typeof data === 'boolean') {\n return String(data);\n }\n\n if (data instanceof Error) {\n return data.message || undefined;\n }\n\n if (Array.isArray(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n const parts = data\n .map((item) => extractDgiiErrorMessage(item, seen))\n .filter((item): item is string => Boolean(item));\n return parts.length ? truncate(parts.join(' | ')) : undefined;\n }\n\n if (isObject(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n\n const mensajes = readMensajes(data.mensajes ?? data.Mensajes);\n if (mensajes) {\n return truncate(mensajes.map((mensaje) => mensaje.valor).join(' | '));\n }\n\n for (const key of MESSAGE_KEYS) {\n const value = data[key];\n if (typeof value === 'string' && value.trim()) {\n return truncate(collapseWhitespace(value));\n }\n if (key === 'error' && (isObject(value) || Array.isArray(value))) {\n const nested = extractDgiiErrorMessage(value, seen);\n if (nested) {\n return nested;\n }\n }\n }\n\n const errors = data.errors ?? data.Errors;\n if (isObject(errors)) {\n const parts = Object.entries(errors)\n .map(([field, value]) => {\n const nested = extractDgiiErrorMessage(value, seen);\n return nested ? `${field}: ${nested}` : undefined;\n })\n .filter((item): item is string => Boolean(item));\n if (parts.length) {\n return truncate(parts.join(' | '));\n }\n } else if (errors) {\n const nested = extractDgiiErrorMessage(errors, seen);\n if (nested) {\n return nested;\n }\n }\n\n try {\n const serialized = JSON.stringify(data);\n if (serialized && serialized !== '{}') {\n return truncate(serialized);\n }\n } catch {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport class DgiiError extends Error {\n readonly code: DgiiErrorCode;\n readonly status?: number;\n readonly statusText?: string;\n readonly resource?: string;\n readonly method?: string;\n readonly baseURL?: string;\n readonly data?: unknown;\n readonly mensajes?: Mensaje[];\n readonly retryable: boolean;\n\n constructor(message: string, options: DgiiErrorOptions = {}) {\n super(message);\n this.name = 'DgiiError';\n Object.setPrototypeOf(this, DgiiError.prototype);\n\n this.code = options.code ?? 'UNKNOWN';\n this.status = options.status;\n this.statusText = options.statusText;\n this.resource = options.resource;\n this.method = options.method;\n this.baseURL = options.baseURL;\n this.data = options.data;\n this.mensajes = options.mensajes;\n this.retryable = options.retryable ?? isRetryableStatus(options.status);\n\n if (options.cause !== undefined) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n statusText: this.statusText,\n resource: this.resource,\n method: this.method,\n mensajes: this.mensajes,\n data: this.data,\n };\n }\n}\n\nexport interface DgiiErrorContext {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n fallbackMessage?: string;\n}\n\n/** Normalize any thrown value into a {@link DgiiError}. */\nexport const toDgiiError = (\n err: unknown,\n context: DgiiErrorContext = {},\n): DgiiError => {\n if (err instanceof DgiiError) {\n return err;\n }\n\n if (err instanceof Error) {\n return new DgiiError(\n err.message || context.fallbackMessage || 'DGII request failed',\n {\n ...context,\n cause: err,\n },\n );\n }\n\n const message =\n extractDgiiErrorMessage(err) ||\n context.fallbackMessage ||\n 'DGII request failed';\n const status =\n isObject(err) && typeof err.status === 'number'\n ? err.status\n : context.status;\n\n return new DgiiError(message, {\n ...context,\n status,\n data: err,\n mensajes: isObject(err)\n ? readMensajes(err.mensajes ?? err.Mensajes)\n : undefined,\n cause: err,\n });\n};\n","import type { Result } from 'neverthrow';\nimport type { DgiiError } from './errors.js';\n\nexport type { Result } from 'neverthrow';\n\nexport {\n Ok,\n Err,\n ok,\n err,\n okAsync,\n errAsync,\n fromThrowable,\n fromPromise,\n fromSafePromise,\n ResultAsync,\n} from 'neverthrow';\n\n/** A {@link Result} whose failure channel is always {@link DgiiError}. */\nexport type DgiiResult<T> = Result<T, DgiiError>;\n","import {\n ConsecutiveBreaker,\n ExponentialBackoff,\n TimeoutStrategy,\n bulkhead,\n circuitBreaker,\n handleAll,\n handleWhen,\n retry,\n timeout,\n wrap,\n type IPolicy,\n} from 'cockatiel';\nimport { DgiiError } from './errors.js';\n\nexport interface ResilienceOptions {\n /** Maximum number of attempts (including the first). Default 3. */\n maxRetries?: number;\n /** Consecutive failures before the circuit opens. Default 5. */\n breakerThreshold?: number;\n /** Milliseconds the circuit stays open before half-opening. Default 30s. */\n halfOpenAfterMs?: number;\n /** Per-attempt timeout in milliseconds. Default 15s. */\n timeoutMs?: number;\n /** Initial retry backoff delay in milliseconds. Default 100. */\n retryInitialDelayMs?: number;\n /** Maximum concurrent in-flight requests. Default 20. */\n bulkheadLimit?: number;\n /** Maximum queued requests while the bulkhead is saturated. Default 40. */\n bulkheadQueue?: number;\n}\n\nexport const defaultResilienceOptions: Required<ResilienceOptions> = {\n maxRetries: 3,\n breakerThreshold: 5,\n halfOpenAfterMs: 30_000,\n timeoutMs: 15_000,\n retryInitialDelayMs: 100,\n bulkheadLimit: 20,\n bulkheadQueue: 40,\n};\n\n/**\n * Only transient failures are retried: network errors, timeouts, 408, 429 and\n * 5xx. A rejected e-CF (4xx) must never be blindly re-sent.\n */\nexport const isRetryableError = (error: unknown): boolean => {\n if (error instanceof DgiiError) {\n return error.retryable;\n }\n if (error instanceof Error) {\n const name = error.name.toLowerCase();\n const message = error.message.toLowerCase();\n return (\n name === 'typeerror' ||\n name === 'aborterror' ||\n name === 'fetcherror' ||\n name === 'timeouterror' ||\n name.includes('cancel') ||\n message.includes('timeout') ||\n message.includes('aborted') ||\n message.includes('network')\n );\n }\n return false;\n};\n\nexport interface ResiliencePolicies {\n readonly retry: IPolicy;\n readonly circuitBreaker: IPolicy;\n readonly timeout: IPolicy;\n readonly bulkhead: IPolicy;\n /** Composed policy: `retry → circuitBreaker → timeout → bulkhead`. */\n readonly policy: IPolicy;\n}\n\n/** Build the composed resilience policy used by the HTTP client. */\nexport const createResiliencePolicies = (\n options: ResilienceOptions = {},\n): ResiliencePolicies => {\n const opts = { ...defaultResilienceOptions, ...options };\n\n const retryPolicy = retry(handleWhen(isRetryableError), {\n maxAttempts: opts.maxRetries,\n backoff: new ExponentialBackoff({ initialDelay: opts.retryInitialDelayMs }),\n });\n\n const breakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: opts.halfOpenAfterMs,\n breaker: new ConsecutiveBreaker(opts.breakerThreshold),\n });\n\n const timeoutPolicy = timeout(opts.timeoutMs, TimeoutStrategy.Aggressive);\n const bulkheadPolicy = bulkhead(opts.bulkheadLimit, opts.bulkheadQueue);\n\n const policy = wrap(\n retryPolicy,\n breakerPolicy,\n timeoutPolicy,\n bulkheadPolicy,\n );\n\n return {\n retry: retryPolicy,\n circuitBreaker: breakerPolicy,\n timeout: timeoutPolicy,\n bulkhead: bulkheadPolicy,\n policy,\n };\n};\n","import { err, ok, type Result } from './result.js';\nimport { DgiiError, extractDgiiErrorMessage, toDgiiError } from './errors.js';\nimport {\n createResiliencePolicies,\n type ResilienceOptions,\n type ResiliencePolicies,\n} from './resilience.js';\n\n/**\n * Pluggable idempotency store. Provide a Redis/Postgres-backed implementation\n * in production so a retried or duplicated submission never double-issues.\n */\nexport interface IdempotencyStore {\n get<T>(key: string): Promise<T | undefined>;\n set<T>(key: string, value: T): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Process-local default. Fine for single-instance usage and tests. */\nexport class InMemoryIdempotencyStore implements IdempotencyStore {\n private readonly store = new Map<string, unknown>();\n\n async get<T>(key: string): Promise<T | undefined> {\n return this.store.get(key) as T | undefined;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.store.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token?: string;\n resilience?: ResilienceOptions;\n policies?: ResiliencePolicies;\n timeoutMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST';\n /** Absolute URL when `absoluteUrl` is true, otherwise a path appended to baseUrl. */\n path: string;\n absoluteUrl?: boolean;\n headers?: Record<string, string>;\n body?: BodyInit;\n query?: Record<string, string | number | undefined>;\n resource?: string;\n}\n\ninterface RequestContext {\n method: string;\n resource: string;\n baseURL: string;\n}\n\n/** Thin HTTP client over the native `fetch`, wrapped in resilience policies. */\nexport class HttpClient {\n private token?: string;\n private readonly policies: ResiliencePolicies;\n private readonly fetchImpl: typeof fetch;\n private readonly baseUrl: string;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.token = options.token;\n this.policies =\n options.policies ??\n createResiliencePolicies({\n ...options.resilience,\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n });\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n setToken(token: string): void {\n this.token = token;\n }\n\n clearToken(): void {\n this.token = undefined;\n }\n\n private buildUrl(\n path: string,\n absoluteUrl: boolean | undefined,\n query: RequestOptions['query'],\n ): string {\n let url = absoluteUrl\n ? path\n : `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;\n\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== '') {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) {\n url += (url.includes('?') ? '&' : '?') + qs;\n }\n }\n return url;\n }\n\n private authHeaders(extra?: Record<string, string>): Record<string, string> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (this.token) {\n headers.Authorization = `Bearer ${this.token}`;\n }\n return { ...headers, ...extra };\n }\n\n private async readBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? '';\n try {\n if (contentType.includes('json')) {\n return await response.json();\n }\n const text = await response.text();\n return text.length ? text : undefined;\n } catch {\n return undefined;\n }\n }\n\n private async parseResponse<T>(\n response: Response,\n ctx: RequestContext,\n ): Promise<Result<T, DgiiError>> {\n const data = await this.readBody(response);\n\n if (response.ok) {\n return ok(data as T);\n }\n\n const message =\n extractDgiiErrorMessage(data) ??\n `DGII request failed with status ${response.status}`;\n const error = new DgiiError(message, {\n code: response.status === 401 ? 'AUTH' : 'HTTP',\n status: response.status,\n statusText: response.statusText,\n resource: ctx.resource,\n method: ctx.method,\n baseURL: ctx.baseURL,\n data,\n });\n\n // Throw retryable failures so the retry/breaker policies can act on them;\n // non-retryable client errors are returned as a typed failure.\n if (error.retryable) {\n throw error;\n }\n return err(error);\n }\n\n async request<T>(options: RequestOptions): Promise<Result<T, DgiiError>> {\n const url = this.buildUrl(options.path, options.absoluteUrl, options.query);\n const method = options.method ?? 'GET';\n const headers = this.authHeaders(options.headers);\n const ctx: RequestContext = {\n method,\n resource: options.resource ?? options.path,\n baseURL: this.baseUrl,\n };\n\n try {\n return await this.policies.policy.execute(async ({ signal }) => {\n const response = await this.fetchImpl(url, {\n method,\n headers,\n body: options.body,\n signal,\n });\n return this.parseResponse<T>(response, ctx);\n });\n } catch (error) {\n return err(toDgiiError(error, ctx));\n }\n }\n\n get<T>(\n path: string,\n query?: RequestOptions['query'],\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n return this.request<T>({\n method: 'GET',\n path,\n query,\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n\n /**\n * POST a signed XML as a multipart `xml` file part. The runtime computes\n * `Content-Length` from the Blob — never set it manually.\n */\n postMultipart<T>(\n path: string,\n fileName: string,\n xml: string,\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n const form = new FormData();\n form.append('xml', new Blob([xml], { type: 'application/xml' }), fileName);\n return this.request<T>({\n method: 'POST',\n path,\n body: form,\n headers: { Accept: 'application/json' },\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n}\n","import { readFileSync } from 'node:fs';\nimport forge from 'node-forge';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport interface P12ReaderData {\n key?: string;\n cert?: string;\n publicKey?: string;\n}\n\nexport interface CertificateInfo {\n subject: string;\n issuer: string;\n validFrom: Date;\n validTo: Date;\n serialNumber: string;\n}\n\nconst asErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\n/** Reads a PKCS#12 (.p12) bundle and extracts the private key + certificate. */\nexport class P12Reader {\n constructor(private readonly passphrase: string) {}\n\n private load(base64: string): forge.pkcs12.Pkcs12Pfx {\n const der = forge.util.decode64(base64);\n const asn1 = forge.asn1.fromDer(der);\n return forge.pkcs12.pkcs12FromAsn1(asn1, false, this.passphrase);\n }\n\n private extractKey(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n // DGII bundles normally carry a shrouded (encrypted) PKCS#8 key bag, but\n // unencrypted bundles use a plain keyBag. A certBag never holds a private\n // key, so it must not be used as a fallback.\n const keyBagTypes = [\n forge.pki.oids.pkcs8ShroudedKeyBag,\n forge.pki.oids.keyBag,\n ];\n for (const bagType of keyBagTypes) {\n const bag = p12.getBags({ bagType })[bagType]?.[0];\n if (bag?.key) {\n return forge.pki.privateKeyToPem(bag.key);\n }\n }\n return undefined;\n }\n\n private extractCertificate(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });\n const certBag = certBags[forge.pki.oids.certBag]?.[0];\n if (!certBag?.cert) {\n return undefined;\n }\n return forge.pki.certificateToPem(certBag.cert);\n }\n\n getKeyFromFile(fileName: string): Result<P12ReaderData, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getKeyFromStringBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getKeyFromStringBase64(base64: string): Result<P12ReaderData, DgiiError> {\n try {\n const p12 = this.load(base64);\n const key = this.extractKey(p12);\n const cert = this.extractCertificate(p12);\n if (!key || !cert) {\n return err(\n new DgiiError('PKCS#12 must contain a private key and certificate', {\n code: 'CERTIFICATE',\n }),\n );\n }\n const publicKey = forge.pki.publicKeyToPem(\n forge.pki.certificateFromPem(cert).publicKey,\n );\n return ok({ key, cert, publicKey });\n } catch (error) {\n return err(\n new DgiiError(`Unable to parse .p12: ${asErrorMessage(error)}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n private toCertificateInfo(certPem: string): CertificateInfo {\n const certificate = forge.pki.certificateFromPem(certPem);\n return {\n subject: certificate.subject.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n issuer: certificate.issuer.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n validFrom: certificate.validity.notBefore,\n validTo: certificate.validity.notAfter,\n serialNumber: certificate.serialNumber,\n };\n }\n\n getCertificateInfo(fileName: string): Result<CertificateInfo, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getCertificateInfoFromBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getCertificateInfoFromBase64(\n base64: string,\n ): Result<CertificateInfo, DgiiError> {\n try {\n const certPem = this.extractCertificate(this.load(base64));\n if (!certPem) {\n return err(\n new DgiiError('Certificate not found in PKCS#12', {\n code: 'CERTIFICATE',\n }),\n );\n }\n return ok(this.toCertificateInfo(certPem));\n } catch (error) {\n return err(\n new DgiiError(\n `Unable to extract certificate info: ${asErrorMessage(error)}`,\n { code: 'CERTIFICATE', cause: error },\n ),\n );\n }\n }\n}\n","import crypto from 'node:crypto';\nimport { DOMParser } from '@xmldom/xmldom';\nimport { C14nCanonicalization, SignedXml } from 'xml-crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport type DgiiDocumentType =\n 'SemillaModel' | 'ECF' | 'RFCE' | 'ARECF' | 'ACECF' | 'ANECF' | (string & {});\n\nconst C14N_INCLUSIVE = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';\nconst RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';\nconst SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';\nconst ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature';\n/**\n * Custom digest URI: DGII hashes the inclusive C14N 1.0 form of the referenced\n * document. xml-crypto's built-in SHA-256 hashes its raw serialization, so we\n * register a digest backed by xml-crypto's inclusive C14N implementation.\n */\nconst CUSTOM_DIGEST_URI = 'http://dgii.gov.do/digest/sha256-c14n';\n\ninterface XmldomDocument extends Document {\n childNodes: NodeListOf<ChildNode>;\n}\n\n/**\n * DGII-compatible digest: hash the inclusive C14N 1.0 form of the referenced\n * document — the exact bytes a .NET/DGII verifier computes.\n */\nclass DgiiDigest {\n getHash(xml: string): string {\n const doc = new DOMParser().parseFromString(\n xml,\n ) as unknown as XmldomDocument;\n const canonical = new C14nCanonicalization().process(\n doc as unknown as Node,\n {},\n );\n return crypto\n .createHash('sha256')\n .update(canonical, 'utf8')\n .digest('base64');\n }\n\n getAlgorithmName(): string {\n return SHA256;\n }\n}\n\ninterface StrictParseResult {\n doc: XmldomDocument;\n rootName: string;\n}\n\nconst parseStrict = (xml: string): StrictParseResult => {\n const errors: string[] = [];\n const doc = new DOMParser({\n errorHandler: {\n warning: () => undefined,\n error: (message: string) => errors.push(message),\n fatalError: (message: string) => errors.push(message),\n },\n }).parseFromString(xml, 'text/xml') as unknown as XmldomDocument;\n\n if (errors.length) {\n throw new Error(`Invalid XML: ${errors.join('; ')}`);\n }\n const root = doc.documentElement;\n if (!root) {\n throw new Error('Unable to parse XML or find root element');\n }\n if (root.nodeName === 'parsererror' || root.localName === 'parsererror') {\n throw new Error(`Invalid XML: ${root.textContent ?? 'parse error'}`);\n }\n return {\n doc,\n rootName: root.localName ?? root.nodeName,\n };\n};\n\n/** Remove whitespace-only text nodes and comments before canonicalization. */\nconst cleanNodes = (node: Node): void => {\n for (let index = 0; index < node.childNodes.length; index += 1) {\n const child = node.childNodes[index];\n if (!child) {\n continue;\n }\n const isComment = child.nodeType === 8;\n const isWhitespace =\n child.nodeType === 3 && !/\\S/.test(child.nodeValue ?? '');\n if (isComment || isWhitespace) {\n node.removeChild(child);\n index -= 1;\n } else if (child.nodeType === 1) {\n cleanNodes(child);\n }\n }\n};\n\n/** Signs DGII XML documents with XMLDSig (enveloped, inclusive C14N, RSA-SHA256). */\nexport class Signature {\n constructor(\n private readonly privateKey: string,\n private readonly certificatePem: string,\n ) {}\n\n signXml(\n xml: string,\n rootElName?: DgiiDocumentType,\n ): Result<string, DgiiError> {\n let parsed: StrictParseResult;\n try {\n parsed = parseStrict(xml);\n } catch (error) {\n // Malformed input is an INVALID_XML error, not a signing failure —\n // aligning with the Python SDK.\n return err(\n new DgiiError(\n error instanceof Error\n ? error.message\n : `Invalid XML: ${String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n\n try {\n const { doc, rootName } = parsed;\n const elementName = rootElName ?? rootName;\n\n const sig = new SignedXml({\n privateKey: this.privateKey,\n publicCert: this.certificatePem,\n signatureAlgorithm: RSA_SHA256,\n canonicalizationAlgorithm: C14N_INCLUSIVE,\n });\n\n const hashAlgorithms = (\n sig as unknown as {\n HashAlgorithms: Record<string, unknown>;\n }\n ).HashAlgorithms;\n hashAlgorithms[CUSTOM_DIGEST_URI] = DgiiDigest;\n\n sig.addReference({\n xpath: `//*[local-name(.)='${elementName}']`,\n transforms: [ENVELOPED],\n digestAlgorithm: CUSTOM_DIGEST_URI,\n isEmptyUri: true,\n } as unknown as Parameters<SignedXml['addReference']>[0]);\n\n cleanNodes(doc as unknown as Node);\n sig.computeSignature(doc.toString());\n return ok(sig.getSignedXml());\n } catch (error) {\n return err(\n new DgiiError(\n `Failed to sign XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'SIGNING', cause: error },\n ),\n );\n }\n }\n}\n\nexport interface XmlCertificateValidation {\n isValid: boolean;\n subject?: string;\n issuer?: string;\n validFrom?: string;\n validTo?: string;\n error?: string;\n}\n\n/**\n * Matches `<X509Certificate>` with or without a namespace prefix (`ds:`).\n */\nconst X509_CERTIFICATE_RE =\n /<(?:[\\w]+:)?X509Certificate>([\\s\\S]*?)<\\/(?:[\\w]+:)?X509Certificate>/;\n\n/** Validate the embedded X509 certificate of a signed XML document. */\nexport const validateXMLCertificate = (\n xml: string,\n): XmlCertificateValidation => {\n try {\n const match = xml.match(X509_CERTIFICATE_RE);\n if (!match?.[1]) {\n return { isValid: false, error: 'X509Certificate not found' };\n }\n const der = Buffer.from(match[1].replace(/\\s+/g, ''), 'base64');\n const certificate = new crypto.X509Certificate(der);\n const notBefore = new Date(certificate.validFrom).getTime();\n const notAfter = new Date(certificate.validTo).getTime();\n const now = Date.now();\n const isValid = now >= notBefore && now <= notAfter;\n return {\n isValid,\n subject: certificate.subject,\n issuer: certificate.issuer,\n validFrom: certificate.validFrom,\n validTo: certificate.validTo,\n error: isValid ? undefined : 'Certificate expired or not yet valid',\n };\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n};\n","import convert from 'xml-js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nconst MONETARY_RE = /^(-?)(\\d+)\\.(\\d+)$/;\n\n/** Increment a string of decimal digits (\"267\" -> \"268\", \"999\" -> \"1000\"). */\nconst incrementDigits = (digits: string): string => {\n const chars = digits.split('');\n let index = chars.length - 1;\n while (index >= 0) {\n const current = chars[index];\n if (current === '9') {\n chars[index] = '0';\n index -= 1;\n continue;\n }\n chars[index] = String(Number(current) + 1);\n return chars.join('');\n }\n return `1${chars.join('')}`;\n};\n\n/**\n * Round a decimal string to 2 places with ROUND_HALF_UP semantics.\n *\n * `Number.prototype.toFixed` cannot be used: `(2.675).toFixed(2)` is `'2.67'`\n * because the literal is not representable in binary floating point. DGII\n * expects the decimal, half-up result (`'2.68'`) — the same contract as the\n * Python SDK's `Decimal.quantize(..., rounding=ROUND_HALF_UP)`.\n *\n * Values that are not plain decimals (e.g. `1.0e3`) are returned unchanged.\n */\nexport const roundHalfUpToCents = (value: string): string => {\n const match = MONETARY_RE.exec(value);\n if (!match) {\n return value;\n }\n const sign = match[1] === '-' ? '-' : '';\n const integerPart = (match[2] ?? '0').replace(/^0+(?=\\d)/, '');\n const fractionPart = `${match[3] ?? ''}000`;\n const cents = `${integerPart}${fractionPart.slice(0, 2)}`;\n const rounded = fractionPart[2] >= '5' ? incrementDigits(cents) : cents;\n const padded = rounded.padStart(3, '0');\n return `${sign}${padded.slice(0, -2)}.${padded.slice(-2)}`;\n};\n\n/**\n * Converts between the DGII XML documents and the \"compact\" JSON shape used by\n * `xml-js` (a dict key is an element, an array is a repeated element, and\n * `_attributes` / `_text` carry attributes and text).\n */\nexport class Transformer {\n json2xml(dataObject: object, round = false): Result<string, DgiiError> {\n try {\n const data: Record<string, unknown> = {\n _declaration: { _attributes: { version: '1.0', encoding: 'utf-8' } },\n ...dataObject,\n };\n\n const xml = convert.js2xml(data as convert.ElementCompact, {\n compact: true,\n ignoreComment: true,\n spaces: 2,\n fullTagEmptyElement: true,\n textFn: (value: string, label: string) => {\n if (round && label.toLowerCase() !== 'version') {\n return roundHalfUpToCents(value);\n }\n return value;\n },\n });\n\n return ok(xml);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting JSON to XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n\n xml2json<T>(xml: string): Result<T, DgiiError> {\n try {\n const json = convert.xml2js(xml, {\n compact: true,\n ignoreComment: true,\n nativeType: false,\n });\n return ok(json as T);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting XML to JSON: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n}\n","import { BaseUrl, Environment } from './environment.js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport { Transformer } from './transformer.js';\n\n/**\n * Matches `<SignatureValue>` with or without a namespace prefix (`ds:`), which\n * is how .NET and other XMLDSig implementations emit the signature.\n */\nconst SIGNATURE_VALUE_RE =\n /<(?:[\\w]+:)?SignatureValue>([\\s\\S]*?)<\\/(?:[\\w]+:)?SignatureValue>/;\n\n/** First 6 chars of the `<SignatureValue>` (DGII security code). */\nexport const getCodeSixDigitfromSignature = (\n signedXml: string,\n): Result<string, DgiiError> => {\n const match = signedXml.match(SIGNATURE_VALUE_RE);\n const value = match?.[1]?.trim();\n if (!value) {\n return err(new DgiiError('SignatureValue not found', { code: 'SIGNING' }));\n }\n if (value.length < 6) {\n return err(\n new DgiiError('SignatureValue is too short', { code: 'SIGNING' }),\n );\n }\n return ok(value.slice(0, 6));\n};\n\n/** QR URL for a factura de consumo (FC). */\nexport const generateFcQRCodeURL = (\n rncemisor: string,\n encf: string,\n montototal: number,\n codigoseguridad: string,\n env: Environment,\n): string =>\n `${BaseUrl.CF}/${env.toLowerCase()}/consultatimbrefc?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&encf=${encodeURIComponent(encf)}&montototal=${encodeURIComponent(\n String(montototal),\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n\n/** QR URL for a crédito fiscal (e-CF). */\nexport const generateEcfQRCodeURL = (\n rncemisor: string,\n rncComprador: string,\n encf: string,\n montototal: string,\n fechaEmision: string,\n fechaFirma: string,\n codigoseguridad: string,\n env: Environment,\n): string => {\n let rncCompradorParam = '';\n if (rncComprador && !/E43/i.test(encf) && !/E47/i.test(encf)) {\n rncCompradorParam = `RncComprador=${encodeURIComponent(rncComprador)}&`;\n }\n return `${BaseUrl.ECF}/${env.toLowerCase()}/consultatimbre?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&${rncCompradorParam}encf=${encodeURIComponent(\n encf,\n )}&fechaemision=${encodeURIComponent(\n fechaEmision,\n )}&montototal=${encodeURIComponent(\n montototal,\n )}&fechafirma=${encodeURIComponent(\n fechaFirma,\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n};\n\nconst formatInSantoDomingo = (date: Date, withTime: boolean): string => {\n const parts = new Intl.DateTimeFormat('es-DO', {\n timeZone: 'America/Santo_Domingo',\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n ...(withTime\n ? { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }\n : {}),\n })\n .formatToParts(date)\n .reduce<Record<string, string>>((acc, part) => {\n acc[part.type] = part.value;\n return acc;\n }, {});\n\n const datePart = `${parts.day}-${parts.month}-${parts.year}`;\n return withTime\n ? `${datePart} ${parts.hour}:${parts.minute}:${parts.second}`\n : datePart;\n};\n\n/** `DD-MM-YYYY HH:mm:ss` in America/Santo_Domingo. */\nexport const getCurrentFormattedDateTime = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, true);\n\n/** `DD-MM-YYYY` in America/Santo_Domingo. */\nexport const getCurrentFormattedDate = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, false);\n\n/** Extract the XML payload embedded in a DGII commercial-approval body. */\nexport const getXmlFromBodyResponse = (\n body: string,\n lastTagName = 'ACECF',\n): string | undefined =>\n body.match(new RegExp(`<\\\\?xml[\\\\s\\\\S]*?<\\\\/${lastTagName}>`))?.[0];\n\ninterface CompactElement {\n _text?: string;\n [key: string]: unknown;\n}\n\ninterface ImpuestoAdicional {\n TipoImpuesto?: CompactElement;\n MontoImpuestoSelectivoConsumoEspecifico?: CompactElement;\n MontoImpuestoSelectivoConsumoAdvalorem?: CompactElement;\n OtrosImpuestosAdicionales?: CompactElement;\n}\n\ninterface EcfTotales {\n MontoGravadoTotal?: CompactElement;\n MontoGravadoI1?: CompactElement;\n MontoGravadoI2?: CompactElement;\n MontoGravadoI3?: CompactElement;\n MontoExento?: CompactElement;\n TotalITBIS?: CompactElement;\n TotalITBIS1?: CompactElement;\n TotalITBIS2?: CompactElement;\n TotalITBIS3?: CompactElement;\n MontoImpuestoAdicional?: CompactElement;\n ImpuestosAdicionales?: {\n ImpuestoAdicional?: ImpuestoAdicional | ImpuestoAdicional[];\n };\n MontoTotal?: CompactElement;\n MontoNoFacturable?: CompactElement;\n MontoPeriodo?: CompactElement;\n}\n\ninterface EcfJson {\n ECF: {\n Encabezado?: {\n Version?: CompactElement;\n IdDoc?: {\n TipoeCF?: CompactElement;\n eNCF?: CompactElement;\n TipoIngresos?: CompactElement;\n TipoPago?: CompactElement;\n TablaFormasPago?: CompactElement;\n };\n Emisor?: {\n RNCEmisor?: CompactElement;\n RazonSocialEmisor?: CompactElement;\n FechaEmision?: CompactElement;\n };\n Comprador?: {\n RNCComprador?: CompactElement;\n IdentificadorExtranjero?: CompactElement;\n RazonSocialComprador?: CompactElement;\n };\n Totales?: EcfTotales;\n };\n };\n}\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (value === undefined || value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n};\n\nconst isEmptyObject = (value: unknown): boolean =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value as Record<string, unknown>).length === 0;\n\nconst removeEmptyValues = (input: unknown): unknown => {\n if (input === null || input === undefined || input === '') {\n return undefined;\n }\n if (Array.isArray(input)) {\n const filtered = input\n .map(removeEmptyValues)\n .filter(\n (item) =>\n item !== null &&\n item !== undefined &&\n item !== '' &&\n !isEmptyObject(item),\n );\n return filtered.length ? filtered : undefined;\n }\n if (typeof input === 'object') {\n const output: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(\n input as Record<string, unknown>,\n )) {\n const cleaned = removeEmptyValues(value);\n if (cleaned !== undefined && cleaned !== '' && !isEmptyObject(cleaned)) {\n output[key] = cleaned;\n }\n }\n return Object.keys(output).length ? output : undefined;\n }\n return input;\n};\n\n/**\n * Build the RFCE (summary invoice) document from a signed ECF-32 document.\n * Returns the unsigned RFCE XML plus the 6-digit security code.\n */\nexport const convertECF32ToRFCE = (\n ecf32Xml: string,\n): Result<{ xml: string; securityCode: string }, DgiiError> => {\n const securityCode = getCodeSixDigitfromSignature(ecf32Xml);\n if (securityCode.isErr()) {\n return err(securityCode.error);\n }\n\n const transformer = new Transformer();\n const parsed = transformer.xml2json<EcfJson>(ecf32Xml);\n if (parsed.isErr()) {\n return err(parsed.error);\n }\n\n const encabezado = parsed.value.ECF.Encabezado;\n const impuestos = toArray(\n encabezado?.Totales?.ImpuestosAdicionales?.ImpuestoAdicional,\n );\n\n const rfce = removeEmptyValues({\n RFCE: {\n Encabezado: {\n Version: encabezado?.Version,\n IdDoc: {\n TipoeCF: encabezado?.IdDoc?.TipoeCF,\n eNCF: encabezado?.IdDoc?.eNCF,\n TipoIngresos: encabezado?.IdDoc?.TipoIngresos,\n TipoPago: encabezado?.IdDoc?.TipoPago,\n TablaFormasPago: encabezado?.IdDoc?.TablaFormasPago,\n },\n Emisor: {\n RNCEmisor: encabezado?.Emisor?.RNCEmisor,\n RazonSocialEmisor: encabezado?.Emisor?.RazonSocialEmisor,\n FechaEmision: encabezado?.Emisor?.FechaEmision,\n },\n Comprador: {\n RNCComprador: encabezado?.Comprador?.RNCComprador,\n IdentificadorExtranjero:\n encabezado?.Comprador?.IdentificadorExtranjero,\n RazonSocialComprador: encabezado?.Comprador?.RazonSocialComprador,\n },\n Totales: {\n MontoGravadoTotal: encabezado?.Totales?.MontoGravadoTotal,\n MontoGravadoI1: encabezado?.Totales?.MontoGravadoI1,\n MontoGravadoI2: encabezado?.Totales?.MontoGravadoI2,\n MontoGravadoI3: encabezado?.Totales?.MontoGravadoI3,\n MontoExento: encabezado?.Totales?.MontoExento,\n TotalITBIS: encabezado?.Totales?.TotalITBIS,\n TotalITBIS1: encabezado?.Totales?.TotalITBIS1,\n TotalITBIS2: encabezado?.Totales?.TotalITBIS2,\n TotalITBIS3: encabezado?.Totales?.TotalITBIS3,\n MontoImpuestoAdicional: encabezado?.Totales?.MontoImpuestoAdicional,\n ImpuestosAdicionales: {\n ImpuestoAdicional: impuestos.map((impuesto) => ({\n TipoImpuesto: impuesto.TipoImpuesto,\n MontoImpuestoSelectivoConsumoEspecifico:\n impuesto.MontoImpuestoSelectivoConsumoEspecifico,\n MontoImpuestoSelectivoConsumoAdvalorem:\n impuesto.MontoImpuestoSelectivoConsumoAdvalorem,\n OtrosImpuestosAdicionales: impuesto.OtrosImpuestosAdicionales,\n })),\n },\n MontoTotal: encabezado?.Totales?.MontoTotal,\n MontoNoFacturable: encabezado?.Totales?.MontoNoFacturable,\n MontoPeriodo: encabezado?.Totales?.MontoPeriodo,\n },\n CodigoSeguridadeCF: securityCode.value,\n },\n },\n });\n\n if (typeof rfce !== 'object' || rfce === null) {\n return err(\n new DgiiError('Unable to build RFCE document', { code: 'VALIDATION' }),\n );\n }\n\n const xml = transformer.json2xml(rfce);\n if (xml.isErr()) {\n return err(xml.error);\n }\n\n return ok({ xml: xml.value, securityCode: securityCode.value });\n};\n","import { createHash } from 'node:crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport {\n BaseUrl,\n Endpoint,\n Environment,\n SenderReceiverEndpoint,\n buildSenderReceiverUrl,\n buildUrl,\n} from './environment.js';\nimport {\n HttpClient,\n InMemoryIdempotencyStore,\n type IdempotencyStore,\n} from './http.js';\nimport type { ResilienceOptions } from './resilience.js';\nimport { Signature } from './signing.js';\nimport type { P12ReaderData } from './certificate.js';\nimport type {\n AuthToken,\n CommercialApprovalResponse,\n InquiryInvoiceSummary,\n InquiryStatusResponse,\n InvoiceResponse,\n InvoiceSummaryResponse,\n ServiceDirectoryResponse,\n SummaryTrackingStatusResponse,\n TrackingStatusResponse,\n VoidNCFResponse,\n} from './types.js';\n\nexport interface EcfOptions {\n /** Pre-existing bearer token (skips the authentication round-trip). */\n token?: string;\n /** Pluggable idempotency store; defaults to an in-memory store. */\n idempotencyStore?: IdempotencyStore;\n resilience?: ResilienceOptions;\n timeoutMs?: number;\n /** Injectable fetch (useful for tests). */\n fetchImpl?: typeof fetch;\n}\n\ninterface PendingSubmission {\n readonly pending: true;\n}\n\nconst PENDING_SUBMISSION: PendingSubmission = { pending: true };\n\nconst isPendingSubmission = (value: unknown): value is PendingSubmission =>\n typeof value === 'object' &&\n value !== null &&\n (value as { pending?: unknown }).pending === true;\n\nconst sha256Hex = (value: string): string =>\n createHash('sha256').update(value, 'utf8').digest('hex');\n\nconst extractTag = (xml: string, tag: string): string | undefined => {\n const match = xml.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));\n return match?.[1]?.trim();\n};\n\n/**\n * DGII e-CF client. Every method returns a `Result` — no thrown domain errors.\n */\nexport class ECF {\n private readonly environment: Environment;\n private readonly http: HttpClient;\n private readonly idempotency: IdempotencyStore;\n private readonly credentials: P12ReaderData;\n private readonly inFlight = new Map<\n string,\n Promise<Result<unknown, DgiiError>>\n >();\n\n constructor(\n credentials: P12ReaderData,\n environment: Environment = Environment.Dev,\n options: EcfOptions = {},\n ) {\n this.credentials = credentials;\n this.environment = environment;\n this.idempotency =\n options.idempotencyStore ?? new InMemoryIdempotencyStore();\n this.http = new HttpClient({\n baseUrl: BaseUrl.ECF,\n ...(options.token !== undefined ? { token: options.token } : {}),\n ...(options.resilience !== undefined\n ? { resilience: options.resilience }\n : {}),\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n ...(options.fetchImpl !== undefined\n ? { fetchImpl: options.fetchImpl }\n : {}),\n });\n }\n\n private buildIdempotencyKey(signedXml: string): string {\n const rnc = extractTag(signedXml, 'RNCEmisor') ?? 'unknown-rnc';\n const encf = extractTag(signedXml, 'eNCF') ?? 'unknown-encf';\n return `${rnc}:${encf}:${sha256Hex(signedXml)}`;\n }\n\n private async singleFlight<T>(\n key: string,\n task: () => Promise<Result<T, DgiiError>>,\n ): Promise<Result<T, DgiiError>> {\n const existing = this.inFlight.get(key);\n if (existing) {\n return existing as Promise<Result<T, DgiiError>>;\n }\n const promise = task();\n this.inFlight.set(key, promise as Promise<Result<unknown, DgiiError>>);\n try {\n return await promise;\n } finally {\n this.inFlight.delete(key);\n }\n }\n\n /** Authenticate against DGII (or a buyer host) and store the bearer token. */\n async authenticate(\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const seed = await this.getSeed(buyerHost);\n if (seed.isErr()) {\n return err(seed.error);\n }\n if (\n typeof this.credentials.key !== 'string' ||\n typeof this.credentials.cert !== 'string'\n ) {\n return err(\n new DgiiError(\n 'A private key and certificate PEM are required to authenticate',\n { code: 'CERTIFICATE' },\n ),\n );\n }\n\n const signed = new Signature(\n this.credentials.key,\n this.credentials.cert,\n ).signXml(seed.value, 'SemillaModel');\n if (signed.isErr()) {\n return err(signed.error);\n }\n\n const token = await this.getAuthToken(signed.value, buyerHost);\n if (token.isErr()) {\n return err(token.error);\n }\n this.http.setToken(token.value.token);\n return ok(token.value);\n }\n\n private getSeed(buyerHost?: string): Promise<Result<string, DgiiError>> {\n if (buyerHost) {\n const url = buildSenderReceiverUrl(\n buyerHost,\n SenderReceiverEndpoint.Seed,\n );\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: SenderReceiverEndpoint.Seed,\n });\n }\n const url = buildUrl(this.environment, Endpoint.Seed);\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: Endpoint.Seed,\n });\n }\n\n private getAuthToken(\n signedSeed: string,\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.ValidateSeed)\n : buildUrl(this.environment, Endpoint.ValidateSeed);\n return this.http.postMultipart<AuthToken>(url, 'signed.xml', signedSeed, {\n absoluteUrl: true,\n resource: Endpoint.ValidateSeed,\n });\n }\n\n /**\n * Submit a signed e-CF. Idempotent on `RNC + eNCF + SHA-256(signed XML)`:\n * a repeated call returns the cached response instead of double-issuing.\n */\n async sendElectronicDocument(\n signedXml: string,\n fileName: string,\n buyerHost?: string,\n ): Promise<Result<InvoiceResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit: record the pending submission before the\n // network call so an interrupted send can be reconciled, not re-issued.\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.SendInvoice)\n : buildUrl(this.environment, Endpoint.SendInvoice);\n const result = await this.http.postMultipart<InvoiceResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendInvoice },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n /** Submit a signed summary invoice (RFCE). Idempotent like submissions. */\n async sendSummary(\n signedXml: string,\n fileName: string,\n ): Promise<Result<InvoiceSummaryResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceSummaryResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit (see sendElectronicDocument).\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buildUrl(this.environment, Endpoint.SendSummary, BaseUrl.CF);\n const result = await this.http.postMultipart<InvoiceSummaryResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendSummary },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n statusTrackId(\n trackId: string,\n ): Promise<Result<TrackingStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.TrackResultStatus);\n return this.http.get<TrackingStatusResponse>(\n url,\n { trackId },\n { absoluteUrl: true, resource: Endpoint.TrackResultStatus },\n );\n }\n\n inquiryStatus(\n rncEmisor: string,\n ncfElectronico: string,\n rncComprador?: string,\n codigoSeguridad?: string,\n ): Promise<Result<InquiryStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.InquiryStatus);\n return this.http.get<InquiryStatusResponse>(\n url,\n { rncEmisor, ncfElectronico, rncComprador, codigoSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryStatus },\n );\n }\n\n trackStatuses(\n rncEmisor: string,\n encf: string,\n ): Promise<Result<SummaryTrackingStatusResponse[], DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.AllTrackingEcf);\n return this.http.get<SummaryTrackingStatusResponse[]>(\n url,\n { rncEmisor, encf },\n { absoluteUrl: true, resource: Endpoint.AllTrackingEcf },\n );\n }\n\n /** Normalizes DGII's inconsistent (array | single object) directory payload. */\n async getCustomerDirectory(\n rnc: string,\n ): Promise<Result<ServiceDirectoryResponse[] | undefined, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Directory);\n const result = await this.http.get<\n ServiceDirectoryResponse[] | ServiceDirectoryResponse\n >(url, { rnc }, { absoluteUrl: true, resource: Endpoint.Directory });\n if (result.isErr()) {\n return err(result.error);\n }\n const data = result.value;\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n return ok(Array.isArray(data) ? data : [data]);\n }\n\n /** RFCE inquiry — DGII production only. */\n async getSummaryInvoiceInquiry(\n rnc: string,\n encf: string,\n codSeguridad: string,\n ): Promise<Result<InquiryInvoiceSummary, DgiiError>> {\n if (this.environment !== Environment.Prod) {\n return err(\n new DgiiError(\n `getSummaryInvoiceInquiry is only available in the production environment (eCF); current environment is ${this.environment}`,\n { code: 'VALIDATION' },\n ),\n );\n }\n const url = buildUrl(\n this.environment,\n Endpoint.InquiryInvoiceSummary,\n BaseUrl.CF,\n );\n return this.http.get<InquiryInvoiceSummary>(\n url,\n { rnc_emisor: rnc, encf, cod_seguridad_eCF: codSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryInvoiceSummary },\n );\n }\n\n sendCommercialApproval(\n signedXml: string,\n fileName: string,\n ): Promise<Result<CommercialApprovalResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.CommercialApproval);\n return this.http.postMultipart<CommercialApprovalResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.CommercialApproval },\n );\n }\n\n voidENCF(\n signedXml: string,\n fileName: string,\n ): Promise<Result<VoidNCFResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Void);\n return this.http.postMultipart<VoidNCFResponse>(url, fileName, signedXml, {\n absoluteUrl: true,\n resource: Endpoint.Void,\n });\n }\n}\n"],"mappings":"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","names":["Environment","Endpoint","SenderReceiverEndpoint","TrackStatusEnum","err","forge","crypto","convert","import_node_crypto","url"]}
package/dist/index.d.cts CHANGED
@@ -317,6 +317,17 @@ interface XmlCertificateValidation {
317
317
  /** Validate the embedded X509 certificate of a signed XML document. */
318
318
  declare const validateXMLCertificate: (xml: string) => XmlCertificateValidation;
319
319
 
320
+ /**
321
+ * Round a decimal string to 2 places with ROUND_HALF_UP semantics.
322
+ *
323
+ * `Number.prototype.toFixed` cannot be used: `(2.675).toFixed(2)` is `'2.67'`
324
+ * because the literal is not representable in binary floating point. DGII
325
+ * expects the decimal, half-up result (`'2.68'`) — the same contract as the
326
+ * Python SDK's `Decimal.quantize(..., rounding=ROUND_HALF_UP)`.
327
+ *
328
+ * Values that are not plain decimals (e.g. `1.0e3`) are returned unchanged.
329
+ */
330
+ declare const roundHalfUpToCents: (value: string) => string;
320
331
  /**
321
332
  * Converts between the DGII XML documents and the "compact" JSON shape used by
322
333
  * `xml-js` (a dict key is an element, an array is a repeated element, and
@@ -392,4 +403,4 @@ declare class ECF {
392
403
  voidENCF(signedXml: string, fileName: string): Promise<Result<VoidNCFResponse, DgiiError>>;
393
404
  }
394
405
 
395
- export { type AuthToken, BaseUrl, type BaseUrlKey, type CertificateInfo, type CommercialApprovalResponse, type DgiiDocumentType, DgiiError, type DgiiErrorCode, type DgiiErrorContext, type DgiiErrorOptions, type DgiiResult, ECF, type EcfOptions, Endpoint, Environment, HttpClient, type HttpClientOptions, type IdempotencyStore, InMemoryIdempotencyStore, type InquiryInvoiceSummary, type InquiryStatus, type InquiryStatusCode, type InquiryStatusResponse, type InvoiceResponse, type InvoiceSummaryResponse, type Mensaje, P12Reader, type P12ReaderData, type RequestOptions, type ResilienceOptions, type ResiliencePolicies, SenderReceiverEndpoint, type ServiceDirectoryResponse, Signature, type SummaryTrackingStatusResponse, type TrackStatusCode, TrackStatusEnum, type TrackingStatusResponse, Transformer, type VoidNCFResponse, type XmlCertificateValidation, buildSenderReceiverUrl, buildUrl, convertECF32ToRFCE, createResiliencePolicies, defaultResilienceOptions, extractDgiiErrorMessage, generateEcfQRCodeURL, generateFcQRCodeURL, getCodeSixDigitfromSignature, getCurrentFormattedDate, getCurrentFormattedDateTime, getXmlFromBodyResponse, isRetryableError, isRetryableStatus, toDgiiError, validateXMLCertificate };
406
+ export { type AuthToken, BaseUrl, type BaseUrlKey, type CertificateInfo, type CommercialApprovalResponse, type DgiiDocumentType, DgiiError, type DgiiErrorCode, type DgiiErrorContext, type DgiiErrorOptions, type DgiiResult, ECF, type EcfOptions, Endpoint, Environment, HttpClient, type HttpClientOptions, type IdempotencyStore, InMemoryIdempotencyStore, type InquiryInvoiceSummary, type InquiryStatus, type InquiryStatusCode, type InquiryStatusResponse, type InvoiceResponse, type InvoiceSummaryResponse, type Mensaje, P12Reader, type P12ReaderData, type RequestOptions, type ResilienceOptions, type ResiliencePolicies, SenderReceiverEndpoint, type ServiceDirectoryResponse, Signature, type SummaryTrackingStatusResponse, type TrackStatusCode, TrackStatusEnum, type TrackingStatusResponse, Transformer, type VoidNCFResponse, type XmlCertificateValidation, buildSenderReceiverUrl, buildUrl, convertECF32ToRFCE, createResiliencePolicies, defaultResilienceOptions, extractDgiiErrorMessage, generateEcfQRCodeURL, generateFcQRCodeURL, getCodeSixDigitfromSignature, getCurrentFormattedDate, getCurrentFormattedDateTime, getXmlFromBodyResponse, isRetryableError, isRetryableStatus, roundHalfUpToCents, toDgiiError, validateXMLCertificate };
package/dist/index.d.ts CHANGED
@@ -317,6 +317,17 @@ interface XmlCertificateValidation {
317
317
  /** Validate the embedded X509 certificate of a signed XML document. */
318
318
  declare const validateXMLCertificate: (xml: string) => XmlCertificateValidation;
319
319
 
320
+ /**
321
+ * Round a decimal string to 2 places with ROUND_HALF_UP semantics.
322
+ *
323
+ * `Number.prototype.toFixed` cannot be used: `(2.675).toFixed(2)` is `'2.67'`
324
+ * because the literal is not representable in binary floating point. DGII
325
+ * expects the decimal, half-up result (`'2.68'`) — the same contract as the
326
+ * Python SDK's `Decimal.quantize(..., rounding=ROUND_HALF_UP)`.
327
+ *
328
+ * Values that are not plain decimals (e.g. `1.0e3`) are returned unchanged.
329
+ */
330
+ declare const roundHalfUpToCents: (value: string) => string;
320
331
  /**
321
332
  * Converts between the DGII XML documents and the "compact" JSON shape used by
322
333
  * `xml-js` (a dict key is an element, an array is a repeated element, and
@@ -392,4 +403,4 @@ declare class ECF {
392
403
  voidENCF(signedXml: string, fileName: string): Promise<Result<VoidNCFResponse, DgiiError>>;
393
404
  }
394
405
 
395
- export { type AuthToken, BaseUrl, type BaseUrlKey, type CertificateInfo, type CommercialApprovalResponse, type DgiiDocumentType, DgiiError, type DgiiErrorCode, type DgiiErrorContext, type DgiiErrorOptions, type DgiiResult, ECF, type EcfOptions, Endpoint, Environment, HttpClient, type HttpClientOptions, type IdempotencyStore, InMemoryIdempotencyStore, type InquiryInvoiceSummary, type InquiryStatus, type InquiryStatusCode, type InquiryStatusResponse, type InvoiceResponse, type InvoiceSummaryResponse, type Mensaje, P12Reader, type P12ReaderData, type RequestOptions, type ResilienceOptions, type ResiliencePolicies, SenderReceiverEndpoint, type ServiceDirectoryResponse, Signature, type SummaryTrackingStatusResponse, type TrackStatusCode, TrackStatusEnum, type TrackingStatusResponse, Transformer, type VoidNCFResponse, type XmlCertificateValidation, buildSenderReceiverUrl, buildUrl, convertECF32ToRFCE, createResiliencePolicies, defaultResilienceOptions, extractDgiiErrorMessage, generateEcfQRCodeURL, generateFcQRCodeURL, getCodeSixDigitfromSignature, getCurrentFormattedDate, getCurrentFormattedDateTime, getXmlFromBodyResponse, isRetryableError, isRetryableStatus, toDgiiError, validateXMLCertificate };
406
+ export { type AuthToken, BaseUrl, type BaseUrlKey, type CertificateInfo, type CommercialApprovalResponse, type DgiiDocumentType, DgiiError, type DgiiErrorCode, type DgiiErrorContext, type DgiiErrorOptions, type DgiiResult, ECF, type EcfOptions, Endpoint, Environment, HttpClient, type HttpClientOptions, type IdempotencyStore, InMemoryIdempotencyStore, type InquiryInvoiceSummary, type InquiryStatus, type InquiryStatusCode, type InquiryStatusResponse, type InvoiceResponse, type InvoiceSummaryResponse, type Mensaje, P12Reader, type P12ReaderData, type RequestOptions, type ResilienceOptions, type ResiliencePolicies, SenderReceiverEndpoint, type ServiceDirectoryResponse, Signature, type SummaryTrackingStatusResponse, type TrackStatusCode, TrackStatusEnum, type TrackingStatusResponse, Transformer, type VoidNCFResponse, type XmlCertificateValidation, buildSenderReceiverUrl, buildUrl, convertECF32ToRFCE, createResiliencePolicies, defaultResilienceOptions, extractDgiiErrorMessage, generateEcfQRCodeURL, generateFcQRCodeURL, getCodeSixDigitfromSignature, getCurrentFormattedDate, getCurrentFormattedDateTime, getXmlFromBodyResponse, isRetryableError, isRetryableStatus, roundHalfUpToCents, toDgiiError, validateXMLCertificate };
package/dist/index.js CHANGED
@@ -470,17 +470,15 @@ var P12Reader = class {
470
470
  return forge.pkcs12.pkcs12FromAsn1(asn1, false, this.passphrase);
471
471
  }
472
472
  extractKey(p12) {
473
- const keyBags = p12.getBags({
474
- bagType: forge.pki.oids.pkcs8ShroudedKeyBag
475
- });
476
- const pkcs8Key = keyBags[forge.pki.oids.pkcs8ShroudedKeyBag]?.[0];
477
- if (pkcs8Key?.key) {
478
- return forge.pki.privateKeyToPem(pkcs8Key.key);
479
- }
480
- const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });
481
- const certBag = certBags[forge.pki.oids.certBag]?.[0];
482
- if (certBag?.key) {
483
- return forge.pki.privateKeyToPem(certBag.key);
473
+ const keyBagTypes = [
474
+ forge.pki.oids.pkcs8ShroudedKeyBag,
475
+ forge.pki.oids.keyBag
476
+ ];
477
+ for (const bagType of keyBagTypes) {
478
+ const bag = p12.getBags({ bagType })[bagType]?.[0];
479
+ if (bag?.key) {
480
+ return forge.pki.privateKeyToPem(bag.key);
481
+ }
484
482
  }
485
483
  return void 0;
486
484
  }
@@ -647,8 +645,19 @@ var Signature = class {
647
645
  privateKey;
648
646
  certificatePem;
649
647
  signXml(xml, rootElName) {
648
+ let parsed;
649
+ try {
650
+ parsed = parseStrict(xml);
651
+ } catch (error) {
652
+ return err(
653
+ new DgiiError(
654
+ error instanceof Error ? error.message : `Invalid XML: ${String(error)}`,
655
+ { code: "INVALID_XML", cause: error }
656
+ )
657
+ );
658
+ }
650
659
  try {
651
- const { doc, rootName } = parseStrict(xml);
660
+ const { doc, rootName } = parsed;
652
661
  const elementName = rootElName ?? rootName;
653
662
  const sig = new SignedXml({
654
663
  privateKey: this.privateKey,
@@ -677,9 +686,10 @@ var Signature = class {
677
686
  }
678
687
  }
679
688
  };
689
+ var X509_CERTIFICATE_RE = /<(?:[\w]+:)?X509Certificate>([\s\S]*?)<\/(?:[\w]+:)?X509Certificate>/;
680
690
  var validateXMLCertificate = (xml) => {
681
691
  try {
682
- const match = xml.match(/<X509Certificate>([\s\S]*?)<\/X509Certificate>/);
692
+ const match = xml.match(X509_CERTIFICATE_RE);
683
693
  if (!match?.[1]) {
684
694
  return { isValid: false, error: "X509Certificate not found" };
685
695
  }
@@ -707,6 +717,35 @@ var validateXMLCertificate = (xml) => {
707
717
 
708
718
  // src/transformer.ts
709
719
  import convert from "xml-js";
720
+ var MONETARY_RE = /^(-?)(\d+)\.(\d+)$/;
721
+ var incrementDigits = (digits) => {
722
+ const chars = digits.split("");
723
+ let index = chars.length - 1;
724
+ while (index >= 0) {
725
+ const current = chars[index];
726
+ if (current === "9") {
727
+ chars[index] = "0";
728
+ index -= 1;
729
+ continue;
730
+ }
731
+ chars[index] = String(Number(current) + 1);
732
+ return chars.join("");
733
+ }
734
+ return `1${chars.join("")}`;
735
+ };
736
+ var roundHalfUpToCents = (value) => {
737
+ const match = MONETARY_RE.exec(value);
738
+ if (!match) {
739
+ return value;
740
+ }
741
+ const sign = match[1] === "-" ? "-" : "";
742
+ const integerPart = (match[2] ?? "0").replace(/^0+(?=\d)/, "");
743
+ const fractionPart = `${match[3] ?? ""}000`;
744
+ const cents = `${integerPart}${fractionPart.slice(0, 2)}`;
745
+ const rounded = fractionPart[2] >= "5" ? incrementDigits(cents) : cents;
746
+ const padded = rounded.padStart(3, "0");
747
+ return `${sign}${padded.slice(0, -2)}.${padded.slice(-2)}`;
748
+ };
710
749
  var Transformer = class {
711
750
  json2xml(dataObject, round = false) {
712
751
  try {
@@ -720,9 +759,8 @@ var Transformer = class {
720
759
  spaces: 2,
721
760
  fullTagEmptyElement: true,
722
761
  textFn: (value, label) => {
723
- const omits = ["version"];
724
- if (/^\d+\.\d+$/.test(value) && round && !omits.includes(label.toLowerCase())) {
725
- return parseFloat(value).toFixed(2);
762
+ if (round && label.toLowerCase() !== "version") {
763
+ return roundHalfUpToCents(value);
726
764
  }
727
765
  return value;
728
766
  }
@@ -757,8 +795,9 @@ var Transformer = class {
757
795
  };
758
796
 
759
797
  // src/utils.ts
798
+ var SIGNATURE_VALUE_RE = /<(?:[\w]+:)?SignatureValue>([\s\S]*?)<\/(?:[\w]+:)?SignatureValue>/;
760
799
  var getCodeSixDigitfromSignature = (signedXml) => {
761
- const match = signedXml.match(/<SignatureValue>([\s\S]*?)<\/SignatureValue>/);
800
+ const match = signedXml.match(SIGNATURE_VALUE_RE);
762
801
  const value = match?.[1]?.trim();
763
802
  if (!value) {
764
803
  return err(new DgiiError("SignatureValue not found", { code: "SIGNING" }));
@@ -1116,7 +1155,15 @@ var ECF = class {
1116
1155
  return ok(Array.isArray(data) ? data : [data]);
1117
1156
  }
1118
1157
  /** RFCE inquiry — DGII production only. */
1119
- getSummaryInvoiceInquiry(rnc, encf, codSeguridad) {
1158
+ async getSummaryInvoiceInquiry(rnc, encf, codSeguridad) {
1159
+ if (this.environment !== "eCF" /* Prod */) {
1160
+ return err(
1161
+ new DgiiError(
1162
+ `getSummaryInvoiceInquiry is only available in the production environment (eCF); current environment is ${this.environment}`,
1163
+ { code: "VALIDATION" }
1164
+ )
1165
+ );
1166
+ }
1120
1167
  const url = buildUrl(
1121
1168
  this.environment,
1122
1169
  "consultarfce/api/Consultas/Consulta" /* InquiryInvoiceSummary */,
@@ -1182,6 +1229,7 @@ export {
1182
1229
  isRetryableStatus,
1183
1230
  ok,
1184
1231
  okAsync,
1232
+ roundHalfUpToCents,
1185
1233
  toDgiiError,
1186
1234
  validateXMLCertificate
1187
1235
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/environment.ts","../src/types.ts","../src/errors.ts","../src/result.ts","../src/resilience.ts","../src/http.ts","../src/certificate.ts","../src/signing.ts","../src/transformer.ts","../src/utils.ts","../src/client.ts"],"sourcesContent":["export enum Environment {\n /** DGII test environment */\n Dev = 'TesteCF',\n /** DGII certification environment */\n Cert = 'CerteCF',\n /** DGII production environment */\n Prod = 'eCF',\n}\n\nexport const BaseUrl = {\n /** Crédito fiscal / general e-CF services */\n ECF: 'https://ecf.dgii.gov.do',\n /** Factura de consumo (< DOP 250,000) */\n CF: 'https://fc.dgii.gov.do',\n /** DGII service status */\n STATUS: 'https://statusecf.dgii.gov.do',\n} as const;\n\nexport type BaseUrlKey = keyof typeof BaseUrl;\n\nexport enum Endpoint {\n Seed = 'Autenticacion/api/Autenticacion/Semilla',\n ValidateSeed = 'autenticacion/api/Autenticacion/ValidarSemilla',\n SendInvoice = 'recepcion/api/FacturasElectronicas',\n SendSummary = 'recepcionfc/api/recepcion/ecf',\n InquiryInvoiceSummary = 'consultarfce/api/Consultas/Consulta',\n CommercialApproval = 'aprobacionComercial/api/AprobacionComercial',\n TrackResultStatus = 'consultaresultado/api/Consultas/Estado',\n InquiryStatus = 'consultaestado/api/Consultas/Estado',\n AllTrackingEcf = 'ConsultaTrackIds/api/TrackIds/Consulta',\n Directory = 'consultadirectorio/api/consultas/obtenerdirectorioporrnc',\n Void = 'anulacionrangos/api/operaciones/anularrango',\n}\n\n/** Endpoints used when talking to a buyer's Sender↔Receiver host. */\nexport enum SenderReceiverEndpoint {\n Seed = 'fe/autenticacion/api/semilla',\n ValidateSeed = 'fe/autenticacion/api/validacioncertificado',\n SendInvoice = 'fe/recepcion/api/ecf',\n CommercialApproval = 'fe/aprobacioncomercial/api/ecf',\n}\n\n/** Build an absolute DGII URL: `${baseUrl}/${environment}/${endpoint}`. */\nexport const buildUrl = (\n environment: Environment,\n endpoint: Endpoint,\n baseUrl: string = BaseUrl.ECF,\n): string => `${baseUrl.replace(/\\/+$/, '')}/${environment}/${endpoint}`;\n\n/** Build an absolute Sender↔Receiver URL against a buyer host. */\nexport const buildSenderReceiverUrl = (\n host: string,\n endpoint: SenderReceiverEndpoint,\n): string => `${host.replace(/\\/+$/, '')}/${endpoint}`;\n","export interface Mensaje {\n valor: string;\n codigo: number;\n}\n\nexport interface AuthToken {\n token: string;\n expira: string;\n expedido: string;\n}\n\nexport enum TrackStatusEnum {\n NotFound = 'No encontrado',\n Accepted = 'Aceptado',\n Rejected = 'Rechazado',\n InProcess = 'En Proceso',\n ConditionalAccepted = 'Aceptado Condicional',\n}\n\nexport type TrackStatusCode = 0 | 1 | 2 | 3 | 4;\n\nexport interface TrackingStatusResponse {\n trackId: string;\n codigo: TrackStatusCode;\n estado: TrackStatusEnum;\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n fechaRecepcion: string;\n mensajes?: Mensaje[];\n}\n\nexport type InquiryStatusCode = 0 | 1 | 2;\n\nexport type InquiryStatus = 'No encontrado' | 'Aceptado' | 'Rechazado';\n\nexport interface InquiryStatusResponse {\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n rncEmisor?: string;\n ncfElectronico?: string;\n montoTotal?: number;\n totalITBIS?: number;\n fechaEmision?: string;\n fechaFirma?: string;\n rncComprador?: string;\n codigoSeguridad?: string;\n idExtranjero?: string;\n}\n\nexport interface SummaryTrackingStatusResponse {\n trackId: string;\n estado: string;\n fechaRecepcion: string;\n}\n\nexport interface InvoiceResponse {\n trackId?: string;\n error?: string;\n mensajes?: Mensaje[];\n}\n\nexport interface InvoiceSummaryResponse {\n codigo: number;\n estado: 'Aceptado' | 'Rechazado' | 'Aceptado Condicional';\n mensajes?: Mensaje[];\n encf: string;\n secuenciaUtilizada: boolean;\n}\n\nexport interface ServiceDirectoryResponse {\n nombre: string;\n rnc: string;\n urlRecepcion: string;\n urlAceptacion: string;\n urlOpcional: string;\n}\n\nexport interface InquiryInvoiceSummary {\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n mensajes?: Mensaje[];\n}\n\nexport interface CommercialApprovalResponse {\n codigo: '01' | '02';\n estado: 'Aprobación Comercial Aprobada.' | 'Aprobacion Comercial Rechazada.';\n mensaje: string[];\n}\n\nexport interface VoidNCFResponse {\n rnc: string;\n codigo: string;\n nombre: string;\n mensajes: string[];\n}\n","import type { Mensaje } from './types.js';\n\nexport type DgiiErrorCode =\n | 'INVALID_XML'\n | 'CERTIFICATE'\n | 'SIGNING'\n | 'HTTP'\n | 'AUTH'\n | 'TIMEOUT'\n | 'CIRCUIT_OPEN'\n | 'IDEMPOTENCY'\n | 'VALIDATION'\n | 'UNKNOWN';\n\nconst RETRYABLE_STATUSES = new Set<number>([408, 429, 500, 502, 503, 504]);\n\nexport const isRetryableStatus = (status: number | undefined): boolean =>\n status !== undefined && RETRYABLE_STATUSES.has(status);\n\nexport interface DgiiErrorOptions {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n data?: unknown;\n mensajes?: Mensaje[];\n retryable?: boolean;\n cause?: unknown;\n}\n\nconst MAX_RAW = 1000;\n\nconst truncate = (value: string): string =>\n value.length > MAX_RAW ? `${value.slice(0, MAX_RAW)}…` : value;\n\nconst collapseWhitespace = (value: string): string =>\n value.replace(/\\s+/g, ' ').trim();\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst looksLikeHtml = (value: string): boolean =>\n /^\\s*<(?:!doctype|html|body|head)\\b/i.test(value);\n\nconst stripHtml = (value: string): string =>\n collapseWhitespace(\n value\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<[^>]+>/g, ' '),\n );\n\nconst readMensajes = (value: unknown): Mensaje[] | undefined => {\n if (!Array.isArray(value) || value.length === 0) {\n return undefined;\n }\n const out: Mensaje[] = [];\n for (const item of value) {\n if (typeof item === 'string' && item.trim()) {\n out.push({ valor: item.trim(), codigo: 0 });\n } else if (isObject(item) && typeof item.valor === 'string') {\n out.push({\n valor: item.valor,\n codigo: typeof item.codigo === 'number' ? item.codigo : 0,\n });\n }\n }\n return out.length ? out : undefined;\n};\n\nconst MESSAGE_KEYS = [\n 'mensaje',\n 'Mensaje',\n 'message',\n 'Message',\n 'error',\n 'Error',\n 'errorMessage',\n 'error_description',\n 'detail',\n 'Detail',\n 'title',\n 'Title',\n 'descripcion',\n 'Descripcion',\n];\n\n/**\n * Reduce DGII's inconsistent error payloads (bare string, `{ mensajes }`,\n * ASP.NET ProblemDetails/ModelState, or an HTML page) to a single message.\n */\nexport const extractDgiiErrorMessage = (\n data: unknown,\n seen: WeakSet<object> = new WeakSet<object>(),\n): string | undefined => {\n if (data === undefined || data === null) {\n return undefined;\n }\n\n if (typeof data === 'string') {\n const trimmed = data.trim();\n if (!trimmed) {\n return undefined;\n }\n if (/^[[{\"]/.test(trimmed)) {\n try {\n return extractDgiiErrorMessage(JSON.parse(trimmed), seen);\n } catch {\n // Not JSON after all — fall through to raw text.\n }\n }\n if (looksLikeHtml(trimmed)) {\n const text = stripHtml(trimmed);\n return text ? truncate(text) : undefined;\n }\n return truncate(collapseWhitespace(trimmed));\n }\n\n if (typeof data === 'number' || typeof data === 'boolean') {\n return String(data);\n }\n\n if (data instanceof Error) {\n return data.message || undefined;\n }\n\n if (Array.isArray(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n const parts = data\n .map((item) => extractDgiiErrorMessage(item, seen))\n .filter((item): item is string => Boolean(item));\n return parts.length ? truncate(parts.join(' | ')) : undefined;\n }\n\n if (isObject(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n\n const mensajes = readMensajes(data.mensajes ?? data.Mensajes);\n if (mensajes) {\n return truncate(mensajes.map((mensaje) => mensaje.valor).join(' | '));\n }\n\n for (const key of MESSAGE_KEYS) {\n const value = data[key];\n if (typeof value === 'string' && value.trim()) {\n return truncate(collapseWhitespace(value));\n }\n if (key === 'error' && (isObject(value) || Array.isArray(value))) {\n const nested = extractDgiiErrorMessage(value, seen);\n if (nested) {\n return nested;\n }\n }\n }\n\n const errors = data.errors ?? data.Errors;\n if (isObject(errors)) {\n const parts = Object.entries(errors)\n .map(([field, value]) => {\n const nested = extractDgiiErrorMessage(value, seen);\n return nested ? `${field}: ${nested}` : undefined;\n })\n .filter((item): item is string => Boolean(item));\n if (parts.length) {\n return truncate(parts.join(' | '));\n }\n } else if (errors) {\n const nested = extractDgiiErrorMessage(errors, seen);\n if (nested) {\n return nested;\n }\n }\n\n try {\n const serialized = JSON.stringify(data);\n if (serialized && serialized !== '{}') {\n return truncate(serialized);\n }\n } catch {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport class DgiiError extends Error {\n readonly code: DgiiErrorCode;\n readonly status?: number;\n readonly statusText?: string;\n readonly resource?: string;\n readonly method?: string;\n readonly baseURL?: string;\n readonly data?: unknown;\n readonly mensajes?: Mensaje[];\n readonly retryable: boolean;\n\n constructor(message: string, options: DgiiErrorOptions = {}) {\n super(message);\n this.name = 'DgiiError';\n Object.setPrototypeOf(this, DgiiError.prototype);\n\n this.code = options.code ?? 'UNKNOWN';\n this.status = options.status;\n this.statusText = options.statusText;\n this.resource = options.resource;\n this.method = options.method;\n this.baseURL = options.baseURL;\n this.data = options.data;\n this.mensajes = options.mensajes;\n this.retryable = options.retryable ?? isRetryableStatus(options.status);\n\n if (options.cause !== undefined) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n statusText: this.statusText,\n resource: this.resource,\n method: this.method,\n mensajes: this.mensajes,\n data: this.data,\n };\n }\n}\n\nexport interface DgiiErrorContext {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n fallbackMessage?: string;\n}\n\n/** Normalize any thrown value into a {@link DgiiError}. */\nexport const toDgiiError = (\n err: unknown,\n context: DgiiErrorContext = {},\n): DgiiError => {\n if (err instanceof DgiiError) {\n return err;\n }\n\n if (err instanceof Error) {\n return new DgiiError(\n err.message || context.fallbackMessage || 'DGII request failed',\n {\n ...context,\n cause: err,\n },\n );\n }\n\n const message =\n extractDgiiErrorMessage(err) ||\n context.fallbackMessage ||\n 'DGII request failed';\n const status =\n isObject(err) && typeof err.status === 'number'\n ? err.status\n : context.status;\n\n return new DgiiError(message, {\n ...context,\n status,\n data: err,\n mensajes: isObject(err)\n ? readMensajes(err.mensajes ?? err.Mensajes)\n : undefined,\n cause: err,\n });\n};\n","import type { Result } from 'neverthrow';\nimport type { DgiiError } from './errors.js';\n\nexport type { Result } from 'neverthrow';\n\nexport {\n Ok,\n Err,\n ok,\n err,\n okAsync,\n errAsync,\n fromThrowable,\n fromPromise,\n fromSafePromise,\n ResultAsync,\n} from 'neverthrow';\n\n/** A {@link Result} whose failure channel is always {@link DgiiError}. */\nexport type DgiiResult<T> = Result<T, DgiiError>;\n","import {\n ConsecutiveBreaker,\n ExponentialBackoff,\n TimeoutStrategy,\n bulkhead,\n circuitBreaker,\n handleAll,\n handleWhen,\n retry,\n timeout,\n wrap,\n type IPolicy,\n} from 'cockatiel';\nimport { DgiiError } from './errors.js';\n\nexport interface ResilienceOptions {\n /** Maximum number of attempts (including the first). Default 3. */\n maxRetries?: number;\n /** Consecutive failures before the circuit opens. Default 5. */\n breakerThreshold?: number;\n /** Milliseconds the circuit stays open before half-opening. Default 30s. */\n halfOpenAfterMs?: number;\n /** Per-attempt timeout in milliseconds. Default 15s. */\n timeoutMs?: number;\n /** Initial retry backoff delay in milliseconds. Default 100. */\n retryInitialDelayMs?: number;\n /** Maximum concurrent in-flight requests. Default 20. */\n bulkheadLimit?: number;\n /** Maximum queued requests while the bulkhead is saturated. Default 40. */\n bulkheadQueue?: number;\n}\n\nexport const defaultResilienceOptions: Required<ResilienceOptions> = {\n maxRetries: 3,\n breakerThreshold: 5,\n halfOpenAfterMs: 30_000,\n timeoutMs: 15_000,\n retryInitialDelayMs: 100,\n bulkheadLimit: 20,\n bulkheadQueue: 40,\n};\n\n/**\n * Only transient failures are retried: network errors, timeouts, 408, 429 and\n * 5xx. A rejected e-CF (4xx) must never be blindly re-sent.\n */\nexport const isRetryableError = (error: unknown): boolean => {\n if (error instanceof DgiiError) {\n return error.retryable;\n }\n if (error instanceof Error) {\n const name = error.name.toLowerCase();\n const message = error.message.toLowerCase();\n return (\n name === 'typeerror' ||\n name === 'aborterror' ||\n name === 'fetcherror' ||\n name === 'timeouterror' ||\n name.includes('cancel') ||\n message.includes('timeout') ||\n message.includes('aborted') ||\n message.includes('network')\n );\n }\n return false;\n};\n\nexport interface ResiliencePolicies {\n readonly retry: IPolicy;\n readonly circuitBreaker: IPolicy;\n readonly timeout: IPolicy;\n readonly bulkhead: IPolicy;\n /** Composed policy: `retry → circuitBreaker → timeout → bulkhead`. */\n readonly policy: IPolicy;\n}\n\n/** Build the composed resilience policy used by the HTTP client. */\nexport const createResiliencePolicies = (\n options: ResilienceOptions = {},\n): ResiliencePolicies => {\n const opts = { ...defaultResilienceOptions, ...options };\n\n const retryPolicy = retry(handleWhen(isRetryableError), {\n maxAttempts: opts.maxRetries,\n backoff: new ExponentialBackoff({ initialDelay: opts.retryInitialDelayMs }),\n });\n\n const breakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: opts.halfOpenAfterMs,\n breaker: new ConsecutiveBreaker(opts.breakerThreshold),\n });\n\n const timeoutPolicy = timeout(opts.timeoutMs, TimeoutStrategy.Aggressive);\n const bulkheadPolicy = bulkhead(opts.bulkheadLimit, opts.bulkheadQueue);\n\n const policy = wrap(\n retryPolicy,\n breakerPolicy,\n timeoutPolicy,\n bulkheadPolicy,\n );\n\n return {\n retry: retryPolicy,\n circuitBreaker: breakerPolicy,\n timeout: timeoutPolicy,\n bulkhead: bulkheadPolicy,\n policy,\n };\n};\n","import { err, ok, type Result } from './result.js';\nimport { DgiiError, extractDgiiErrorMessage, toDgiiError } from './errors.js';\nimport {\n createResiliencePolicies,\n type ResilienceOptions,\n type ResiliencePolicies,\n} from './resilience.js';\n\n/**\n * Pluggable idempotency store. Provide a Redis/Postgres-backed implementation\n * in production so a retried or duplicated submission never double-issues.\n */\nexport interface IdempotencyStore {\n get<T>(key: string): Promise<T | undefined>;\n set<T>(key: string, value: T): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Process-local default. Fine for single-instance usage and tests. */\nexport class InMemoryIdempotencyStore implements IdempotencyStore {\n private readonly store = new Map<string, unknown>();\n\n async get<T>(key: string): Promise<T | undefined> {\n return this.store.get(key) as T | undefined;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.store.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token?: string;\n resilience?: ResilienceOptions;\n policies?: ResiliencePolicies;\n timeoutMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST';\n /** Absolute URL when `absoluteUrl` is true, otherwise a path appended to baseUrl. */\n path: string;\n absoluteUrl?: boolean;\n headers?: Record<string, string>;\n body?: BodyInit;\n query?: Record<string, string | number | undefined>;\n resource?: string;\n}\n\ninterface RequestContext {\n method: string;\n resource: string;\n baseURL: string;\n}\n\n/** Thin HTTP client over the native `fetch`, wrapped in resilience policies. */\nexport class HttpClient {\n private token?: string;\n private readonly policies: ResiliencePolicies;\n private readonly fetchImpl: typeof fetch;\n private readonly baseUrl: string;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.token = options.token;\n this.policies =\n options.policies ??\n createResiliencePolicies({\n ...options.resilience,\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n });\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n setToken(token: string): void {\n this.token = token;\n }\n\n clearToken(): void {\n this.token = undefined;\n }\n\n private buildUrl(\n path: string,\n absoluteUrl: boolean | undefined,\n query: RequestOptions['query'],\n ): string {\n let url = absoluteUrl\n ? path\n : `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;\n\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== '') {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) {\n url += (url.includes('?') ? '&' : '?') + qs;\n }\n }\n return url;\n }\n\n private authHeaders(extra?: Record<string, string>): Record<string, string> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (this.token) {\n headers.Authorization = `Bearer ${this.token}`;\n }\n return { ...headers, ...extra };\n }\n\n private async readBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? '';\n try {\n if (contentType.includes('json')) {\n return await response.json();\n }\n const text = await response.text();\n return text.length ? text : undefined;\n } catch {\n return undefined;\n }\n }\n\n private async parseResponse<T>(\n response: Response,\n ctx: RequestContext,\n ): Promise<Result<T, DgiiError>> {\n const data = await this.readBody(response);\n\n if (response.ok) {\n return ok(data as T);\n }\n\n const message =\n extractDgiiErrorMessage(data) ??\n `DGII request failed with status ${response.status}`;\n const error = new DgiiError(message, {\n code: response.status === 401 ? 'AUTH' : 'HTTP',\n status: response.status,\n statusText: response.statusText,\n resource: ctx.resource,\n method: ctx.method,\n baseURL: ctx.baseURL,\n data,\n });\n\n // Throw retryable failures so the retry/breaker policies can act on them;\n // non-retryable client errors are returned as a typed failure.\n if (error.retryable) {\n throw error;\n }\n return err(error);\n }\n\n async request<T>(options: RequestOptions): Promise<Result<T, DgiiError>> {\n const url = this.buildUrl(options.path, options.absoluteUrl, options.query);\n const method = options.method ?? 'GET';\n const headers = this.authHeaders(options.headers);\n const ctx: RequestContext = {\n method,\n resource: options.resource ?? options.path,\n baseURL: this.baseUrl,\n };\n\n try {\n return await this.policies.policy.execute(async ({ signal }) => {\n const response = await this.fetchImpl(url, {\n method,\n headers,\n body: options.body,\n signal,\n });\n return this.parseResponse<T>(response, ctx);\n });\n } catch (error) {\n return err(toDgiiError(error, ctx));\n }\n }\n\n get<T>(\n path: string,\n query?: RequestOptions['query'],\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n return this.request<T>({\n method: 'GET',\n path,\n query,\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n\n /**\n * POST a signed XML as a multipart `xml` file part. The runtime computes\n * `Content-Length` from the Blob — never set it manually.\n */\n postMultipart<T>(\n path: string,\n fileName: string,\n xml: string,\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n const form = new FormData();\n form.append('xml', new Blob([xml], { type: 'application/xml' }), fileName);\n return this.request<T>({\n method: 'POST',\n path,\n body: form,\n headers: { Accept: 'application/json' },\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n}\n","import { readFileSync } from 'node:fs';\nimport forge from 'node-forge';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport interface P12ReaderData {\n key?: string;\n cert?: string;\n publicKey?: string;\n}\n\nexport interface CertificateInfo {\n subject: string;\n issuer: string;\n validFrom: Date;\n validTo: Date;\n serialNumber: string;\n}\n\nconst asErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\n/** Reads a PKCS#12 (.p12) bundle and extracts the private key + certificate. */\nexport class P12Reader {\n constructor(private readonly passphrase: string) {}\n\n private load(base64: string): forge.pkcs12.Pkcs12Pfx {\n const der = forge.util.decode64(base64);\n const asn1 = forge.asn1.fromDer(der);\n return forge.pkcs12.pkcs12FromAsn1(asn1, false, this.passphrase);\n }\n\n private extractKey(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n const keyBags = p12.getBags({\n bagType: forge.pki.oids.pkcs8ShroudedKeyBag,\n });\n const pkcs8Key = keyBags[forge.pki.oids.pkcs8ShroudedKeyBag]?.[0];\n if (pkcs8Key?.key) {\n return forge.pki.privateKeyToPem(pkcs8Key.key);\n }\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });\n const certBag = certBags[forge.pki.oids.certBag]?.[0];\n if (certBag?.key) {\n return forge.pki.privateKeyToPem(certBag.key);\n }\n return undefined;\n }\n\n private extractCertificate(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });\n const certBag = certBags[forge.pki.oids.certBag]?.[0];\n if (!certBag?.cert) {\n return undefined;\n }\n return forge.pki.certificateToPem(certBag.cert);\n }\n\n getKeyFromFile(fileName: string): Result<P12ReaderData, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getKeyFromStringBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getKeyFromStringBase64(base64: string): Result<P12ReaderData, DgiiError> {\n try {\n const p12 = this.load(base64);\n const key = this.extractKey(p12);\n const cert = this.extractCertificate(p12);\n if (!key || !cert) {\n return err(\n new DgiiError('PKCS#12 must contain a private key and certificate', {\n code: 'CERTIFICATE',\n }),\n );\n }\n const publicKey = forge.pki.publicKeyToPem(\n forge.pki.certificateFromPem(cert).publicKey,\n );\n return ok({ key, cert, publicKey });\n } catch (error) {\n return err(\n new DgiiError(`Unable to parse .p12: ${asErrorMessage(error)}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n private toCertificateInfo(certPem: string): CertificateInfo {\n const certificate = forge.pki.certificateFromPem(certPem);\n return {\n subject: certificate.subject.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n issuer: certificate.issuer.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n validFrom: certificate.validity.notBefore,\n validTo: certificate.validity.notAfter,\n serialNumber: certificate.serialNumber,\n };\n }\n\n getCertificateInfo(fileName: string): Result<CertificateInfo, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getCertificateInfoFromBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getCertificateInfoFromBase64(\n base64: string,\n ): Result<CertificateInfo, DgiiError> {\n try {\n const certPem = this.extractCertificate(this.load(base64));\n if (!certPem) {\n return err(\n new DgiiError('Certificate not found in PKCS#12', {\n code: 'CERTIFICATE',\n }),\n );\n }\n return ok(this.toCertificateInfo(certPem));\n } catch (error) {\n return err(\n new DgiiError(\n `Unable to extract certificate info: ${asErrorMessage(error)}`,\n { code: 'CERTIFICATE', cause: error },\n ),\n );\n }\n }\n}\n","import crypto from 'node:crypto';\nimport { DOMParser } from '@xmldom/xmldom';\nimport { C14nCanonicalization, SignedXml } from 'xml-crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport type DgiiDocumentType =\n 'SemillaModel' | 'ECF' | 'RFCE' | 'ARECF' | 'ACECF' | 'ANECF' | (string & {});\n\nconst C14N_INCLUSIVE = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';\nconst RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';\nconst SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';\nconst ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature';\n/**\n * Custom digest URI: DGII hashes the inclusive C14N 1.0 form of the referenced\n * document. xml-crypto's built-in SHA-256 hashes its raw serialization, so we\n * register a digest backed by xml-crypto's inclusive C14N implementation.\n */\nconst CUSTOM_DIGEST_URI = 'http://dgii.gov.do/digest/sha256-c14n';\n\ninterface XmldomDocument extends Document {\n childNodes: NodeListOf<ChildNode>;\n}\n\n/**\n * DGII-compatible digest: hash the inclusive C14N 1.0 form of the referenced\n * document — the exact bytes a .NET/DGII verifier computes.\n */\nclass DgiiDigest {\n getHash(xml: string): string {\n const doc = new DOMParser().parseFromString(\n xml,\n ) as unknown as XmldomDocument;\n const canonical = new C14nCanonicalization().process(\n doc as unknown as Node,\n {},\n );\n return crypto\n .createHash('sha256')\n .update(canonical, 'utf8')\n .digest('base64');\n }\n\n getAlgorithmName(): string {\n return SHA256;\n }\n}\n\ninterface StrictParseResult {\n doc: XmldomDocument;\n rootName: string;\n}\n\nconst parseStrict = (xml: string): StrictParseResult => {\n const errors: string[] = [];\n const doc = new DOMParser({\n errorHandler: {\n warning: () => undefined,\n error: (message: string) => errors.push(message),\n fatalError: (message: string) => errors.push(message),\n },\n }).parseFromString(xml, 'text/xml') as unknown as XmldomDocument;\n\n if (errors.length) {\n throw new Error(`Invalid XML: ${errors.join('; ')}`);\n }\n const root = doc.documentElement;\n if (!root) {\n throw new Error('Unable to parse XML or find root element');\n }\n if (root.nodeName === 'parsererror' || root.localName === 'parsererror') {\n throw new Error(`Invalid XML: ${root.textContent ?? 'parse error'}`);\n }\n return {\n doc,\n rootName: root.localName ?? root.nodeName,\n };\n};\n\n/** Remove whitespace-only text nodes and comments before canonicalization. */\nconst cleanNodes = (node: Node): void => {\n for (let index = 0; index < node.childNodes.length; index += 1) {\n const child = node.childNodes[index];\n if (!child) {\n continue;\n }\n const isComment = child.nodeType === 8;\n const isWhitespace =\n child.nodeType === 3 && !/\\S/.test(child.nodeValue ?? '');\n if (isComment || isWhitespace) {\n node.removeChild(child);\n index -= 1;\n } else if (child.nodeType === 1) {\n cleanNodes(child);\n }\n }\n};\n\n/** Signs DGII XML documents with XMLDSig (enveloped, inclusive C14N, RSA-SHA256). */\nexport class Signature {\n constructor(\n private readonly privateKey: string,\n private readonly certificatePem: string,\n ) {}\n\n signXml(\n xml: string,\n rootElName?: DgiiDocumentType,\n ): Result<string, DgiiError> {\n try {\n const { doc, rootName } = parseStrict(xml);\n const elementName = rootElName ?? rootName;\n\n const sig = new SignedXml({\n privateKey: this.privateKey,\n publicCert: this.certificatePem,\n signatureAlgorithm: RSA_SHA256,\n canonicalizationAlgorithm: C14N_INCLUSIVE,\n });\n\n const hashAlgorithms = (\n sig as unknown as {\n HashAlgorithms: Record<string, unknown>;\n }\n ).HashAlgorithms;\n hashAlgorithms[CUSTOM_DIGEST_URI] = DgiiDigest;\n\n sig.addReference({\n xpath: `//*[local-name(.)='${elementName}']`,\n transforms: [ENVELOPED],\n digestAlgorithm: CUSTOM_DIGEST_URI,\n isEmptyUri: true,\n } as unknown as Parameters<SignedXml['addReference']>[0]);\n\n cleanNodes(doc as unknown as Node);\n sig.computeSignature(doc.toString());\n return ok(sig.getSignedXml());\n } catch (error) {\n return err(\n new DgiiError(\n `Failed to sign XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'SIGNING', cause: error },\n ),\n );\n }\n }\n}\n\nexport interface XmlCertificateValidation {\n isValid: boolean;\n subject?: string;\n issuer?: string;\n validFrom?: string;\n validTo?: string;\n error?: string;\n}\n\n/** Validate the embedded X509 certificate of a signed XML document. */\nexport const validateXMLCertificate = (\n xml: string,\n): XmlCertificateValidation => {\n try {\n const match = xml.match(/<X509Certificate>([\\s\\S]*?)<\\/X509Certificate>/);\n if (!match?.[1]) {\n return { isValid: false, error: 'X509Certificate not found' };\n }\n const der = Buffer.from(match[1].replace(/\\s+/g, ''), 'base64');\n const certificate = new crypto.X509Certificate(der);\n const notBefore = new Date(certificate.validFrom).getTime();\n const notAfter = new Date(certificate.validTo).getTime();\n const now = Date.now();\n const isValid = now >= notBefore && now <= notAfter;\n return {\n isValid,\n subject: certificate.subject,\n issuer: certificate.issuer,\n validFrom: certificate.validFrom,\n validTo: certificate.validTo,\n error: isValid ? undefined : 'Certificate expired or not yet valid',\n };\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n};\n","import convert from 'xml-js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\n/**\n * Converts between the DGII XML documents and the \"compact\" JSON shape used by\n * `xml-js` (a dict key is an element, an array is a repeated element, and\n * `_attributes` / `_text` carry attributes and text).\n */\nexport class Transformer {\n json2xml(dataObject: object, round = false): Result<string, DgiiError> {\n try {\n const data: Record<string, unknown> = {\n _declaration: { _attributes: { version: '1.0', encoding: 'utf-8' } },\n ...dataObject,\n };\n\n const xml = convert.js2xml(data as convert.ElementCompact, {\n compact: true,\n ignoreComment: true,\n spaces: 2,\n fullTagEmptyElement: true,\n textFn: (value: string, label: string) => {\n const omits = ['version'];\n if (\n /^\\d+\\.\\d+$/.test(value) &&\n round &&\n !omits.includes(label.toLowerCase())\n ) {\n return parseFloat(value).toFixed(2);\n }\n return value;\n },\n });\n\n return ok(xml);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting JSON to XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n\n xml2json<T>(xml: string): Result<T, DgiiError> {\n try {\n const json = convert.xml2js(xml, {\n compact: true,\n ignoreComment: true,\n nativeType: false,\n });\n return ok(json as T);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting XML to JSON: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n}\n","import { BaseUrl, Environment } from './environment.js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport { Transformer } from './transformer.js';\n\n/** First 6 chars of the `<SignatureValue>` (DGII security code). */\nexport const getCodeSixDigitfromSignature = (\n signedXml: string,\n): Result<string, DgiiError> => {\n const match = signedXml.match(/<SignatureValue>([\\s\\S]*?)<\\/SignatureValue>/);\n const value = match?.[1]?.trim();\n if (!value) {\n return err(new DgiiError('SignatureValue not found', { code: 'SIGNING' }));\n }\n if (value.length < 6) {\n return err(\n new DgiiError('SignatureValue is too short', { code: 'SIGNING' }),\n );\n }\n return ok(value.slice(0, 6));\n};\n\n/** QR URL for a factura de consumo (FC). */\nexport const generateFcQRCodeURL = (\n rncemisor: string,\n encf: string,\n montototal: number,\n codigoseguridad: string,\n env: Environment,\n): string =>\n `${BaseUrl.CF}/${env.toLowerCase()}/consultatimbrefc?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&encf=${encodeURIComponent(encf)}&montototal=${encodeURIComponent(\n String(montototal),\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n\n/** QR URL for a crédito fiscal (e-CF). */\nexport const generateEcfQRCodeURL = (\n rncemisor: string,\n rncComprador: string,\n encf: string,\n montototal: string,\n fechaEmision: string,\n fechaFirma: string,\n codigoseguridad: string,\n env: Environment,\n): string => {\n let rncCompradorParam = '';\n if (rncComprador && !/E43/i.test(encf) && !/E47/i.test(encf)) {\n rncCompradorParam = `RncComprador=${encodeURIComponent(rncComprador)}&`;\n }\n return `${BaseUrl.ECF}/${env.toLowerCase()}/consultatimbre?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&${rncCompradorParam}encf=${encodeURIComponent(\n encf,\n )}&fechaemision=${encodeURIComponent(\n fechaEmision,\n )}&montototal=${encodeURIComponent(\n montototal,\n )}&fechafirma=${encodeURIComponent(\n fechaFirma,\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n};\n\nconst formatInSantoDomingo = (date: Date, withTime: boolean): string => {\n const parts = new Intl.DateTimeFormat('es-DO', {\n timeZone: 'America/Santo_Domingo',\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n ...(withTime\n ? { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }\n : {}),\n })\n .formatToParts(date)\n .reduce<Record<string, string>>((acc, part) => {\n acc[part.type] = part.value;\n return acc;\n }, {});\n\n const datePart = `${parts.day}-${parts.month}-${parts.year}`;\n return withTime\n ? `${datePart} ${parts.hour}:${parts.minute}:${parts.second}`\n : datePart;\n};\n\n/** `DD-MM-YYYY HH:mm:ss` in America/Santo_Domingo. */\nexport const getCurrentFormattedDateTime = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, true);\n\n/** `DD-MM-YYYY` in America/Santo_Domingo. */\nexport const getCurrentFormattedDate = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, false);\n\n/** Extract the XML payload embedded in a DGII commercial-approval body. */\nexport const getXmlFromBodyResponse = (\n body: string,\n lastTagName = 'ACECF',\n): string | undefined =>\n body.match(new RegExp(`<\\\\?xml[\\\\s\\\\S]*?<\\\\/${lastTagName}>`))?.[0];\n\ninterface CompactElement {\n _text?: string;\n [key: string]: unknown;\n}\n\ninterface ImpuestoAdicional {\n TipoImpuesto?: CompactElement;\n MontoImpuestoSelectivoConsumoEspecifico?: CompactElement;\n MontoImpuestoSelectivoConsumoAdvalorem?: CompactElement;\n OtrosImpuestosAdicionales?: CompactElement;\n}\n\ninterface EcfTotales {\n MontoGravadoTotal?: CompactElement;\n MontoGravadoI1?: CompactElement;\n MontoGravadoI2?: CompactElement;\n MontoGravadoI3?: CompactElement;\n MontoExento?: CompactElement;\n TotalITBIS?: CompactElement;\n TotalITBIS1?: CompactElement;\n TotalITBIS2?: CompactElement;\n TotalITBIS3?: CompactElement;\n MontoImpuestoAdicional?: CompactElement;\n ImpuestosAdicionales?: {\n ImpuestoAdicional?: ImpuestoAdicional | ImpuestoAdicional[];\n };\n MontoTotal?: CompactElement;\n MontoNoFacturable?: CompactElement;\n MontoPeriodo?: CompactElement;\n}\n\ninterface EcfJson {\n ECF: {\n Encabezado?: {\n Version?: CompactElement;\n IdDoc?: {\n TipoeCF?: CompactElement;\n eNCF?: CompactElement;\n TipoIngresos?: CompactElement;\n TipoPago?: CompactElement;\n TablaFormasPago?: CompactElement;\n };\n Emisor?: {\n RNCEmisor?: CompactElement;\n RazonSocialEmisor?: CompactElement;\n FechaEmision?: CompactElement;\n };\n Comprador?: {\n RNCComprador?: CompactElement;\n IdentificadorExtranjero?: CompactElement;\n RazonSocialComprador?: CompactElement;\n };\n Totales?: EcfTotales;\n };\n };\n}\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (value === undefined || value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n};\n\nconst isEmptyObject = (value: unknown): boolean =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value as Record<string, unknown>).length === 0;\n\nconst removeEmptyValues = (input: unknown): unknown => {\n if (input === null || input === undefined || input === '') {\n return undefined;\n }\n if (Array.isArray(input)) {\n const filtered = input\n .map(removeEmptyValues)\n .filter(\n (item) =>\n item !== null &&\n item !== undefined &&\n item !== '' &&\n !isEmptyObject(item),\n );\n return filtered.length ? filtered : undefined;\n }\n if (typeof input === 'object') {\n const output: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(\n input as Record<string, unknown>,\n )) {\n const cleaned = removeEmptyValues(value);\n if (cleaned !== undefined && cleaned !== '' && !isEmptyObject(cleaned)) {\n output[key] = cleaned;\n }\n }\n return Object.keys(output).length ? output : undefined;\n }\n return input;\n};\n\n/**\n * Build the RFCE (summary invoice) document from a signed ECF-32 document.\n * Returns the unsigned RFCE XML plus the 6-digit security code.\n */\nexport const convertECF32ToRFCE = (\n ecf32Xml: string,\n): Result<{ xml: string; securityCode: string }, DgiiError> => {\n const securityCode = getCodeSixDigitfromSignature(ecf32Xml);\n if (securityCode.isErr()) {\n return err(securityCode.error);\n }\n\n const transformer = new Transformer();\n const parsed = transformer.xml2json<EcfJson>(ecf32Xml);\n if (parsed.isErr()) {\n return err(parsed.error);\n }\n\n const encabezado = parsed.value.ECF.Encabezado;\n const impuestos = toArray(\n encabezado?.Totales?.ImpuestosAdicionales?.ImpuestoAdicional,\n );\n\n const rfce = removeEmptyValues({\n RFCE: {\n Encabezado: {\n Version: encabezado?.Version,\n IdDoc: {\n TipoeCF: encabezado?.IdDoc?.TipoeCF,\n eNCF: encabezado?.IdDoc?.eNCF,\n TipoIngresos: encabezado?.IdDoc?.TipoIngresos,\n TipoPago: encabezado?.IdDoc?.TipoPago,\n TablaFormasPago: encabezado?.IdDoc?.TablaFormasPago,\n },\n Emisor: {\n RNCEmisor: encabezado?.Emisor?.RNCEmisor,\n RazonSocialEmisor: encabezado?.Emisor?.RazonSocialEmisor,\n FechaEmision: encabezado?.Emisor?.FechaEmision,\n },\n Comprador: {\n RNCComprador: encabezado?.Comprador?.RNCComprador,\n IdentificadorExtranjero:\n encabezado?.Comprador?.IdentificadorExtranjero,\n RazonSocialComprador: encabezado?.Comprador?.RazonSocialComprador,\n },\n Totales: {\n MontoGravadoTotal: encabezado?.Totales?.MontoGravadoTotal,\n MontoGravadoI1: encabezado?.Totales?.MontoGravadoI1,\n MontoGravadoI2: encabezado?.Totales?.MontoGravadoI2,\n MontoGravadoI3: encabezado?.Totales?.MontoGravadoI3,\n MontoExento: encabezado?.Totales?.MontoExento,\n TotalITBIS: encabezado?.Totales?.TotalITBIS,\n TotalITBIS1: encabezado?.Totales?.TotalITBIS1,\n TotalITBIS2: encabezado?.Totales?.TotalITBIS2,\n TotalITBIS3: encabezado?.Totales?.TotalITBIS3,\n MontoImpuestoAdicional: encabezado?.Totales?.MontoImpuestoAdicional,\n ImpuestosAdicionales: {\n ImpuestoAdicional: impuestos.map((impuesto) => ({\n TipoImpuesto: impuesto.TipoImpuesto,\n MontoImpuestoSelectivoConsumoEspecifico:\n impuesto.MontoImpuestoSelectivoConsumoEspecifico,\n MontoImpuestoSelectivoConsumoAdvalorem:\n impuesto.MontoImpuestoSelectivoConsumoAdvalorem,\n OtrosImpuestosAdicionales: impuesto.OtrosImpuestosAdicionales,\n })),\n },\n MontoTotal: encabezado?.Totales?.MontoTotal,\n MontoNoFacturable: encabezado?.Totales?.MontoNoFacturable,\n MontoPeriodo: encabezado?.Totales?.MontoPeriodo,\n },\n CodigoSeguridadeCF: securityCode.value,\n },\n },\n });\n\n if (typeof rfce !== 'object' || rfce === null) {\n return err(\n new DgiiError('Unable to build RFCE document', { code: 'VALIDATION' }),\n );\n }\n\n const xml = transformer.json2xml(rfce);\n if (xml.isErr()) {\n return err(xml.error);\n }\n\n return ok({ xml: xml.value, securityCode: securityCode.value });\n};\n","import { createHash } from 'node:crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport {\n BaseUrl,\n Endpoint,\n Environment,\n SenderReceiverEndpoint,\n buildSenderReceiverUrl,\n buildUrl,\n} from './environment.js';\nimport {\n HttpClient,\n InMemoryIdempotencyStore,\n type IdempotencyStore,\n} from './http.js';\nimport type { ResilienceOptions } from './resilience.js';\nimport { Signature } from './signing.js';\nimport type { P12ReaderData } from './certificate.js';\nimport type {\n AuthToken,\n CommercialApprovalResponse,\n InquiryInvoiceSummary,\n InquiryStatusResponse,\n InvoiceResponse,\n InvoiceSummaryResponse,\n ServiceDirectoryResponse,\n SummaryTrackingStatusResponse,\n TrackingStatusResponse,\n VoidNCFResponse,\n} from './types.js';\n\nexport interface EcfOptions {\n /** Pre-existing bearer token (skips the authentication round-trip). */\n token?: string;\n /** Pluggable idempotency store; defaults to an in-memory store. */\n idempotencyStore?: IdempotencyStore;\n resilience?: ResilienceOptions;\n timeoutMs?: number;\n /** Injectable fetch (useful for tests). */\n fetchImpl?: typeof fetch;\n}\n\ninterface PendingSubmission {\n readonly pending: true;\n}\n\nconst PENDING_SUBMISSION: PendingSubmission = { pending: true };\n\nconst isPendingSubmission = (value: unknown): value is PendingSubmission =>\n typeof value === 'object' &&\n value !== null &&\n (value as { pending?: unknown }).pending === true;\n\nconst sha256Hex = (value: string): string =>\n createHash('sha256').update(value, 'utf8').digest('hex');\n\nconst extractTag = (xml: string, tag: string): string | undefined => {\n const match = xml.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));\n return match?.[1]?.trim();\n};\n\n/**\n * DGII e-CF client. Every method returns a `Result` — no thrown domain errors.\n */\nexport class ECF {\n private readonly environment: Environment;\n private readonly http: HttpClient;\n private readonly idempotency: IdempotencyStore;\n private readonly credentials: P12ReaderData;\n private readonly inFlight = new Map<\n string,\n Promise<Result<unknown, DgiiError>>\n >();\n\n constructor(\n credentials: P12ReaderData,\n environment: Environment = Environment.Dev,\n options: EcfOptions = {},\n ) {\n this.credentials = credentials;\n this.environment = environment;\n this.idempotency =\n options.idempotencyStore ?? new InMemoryIdempotencyStore();\n this.http = new HttpClient({\n baseUrl: BaseUrl.ECF,\n ...(options.token !== undefined ? { token: options.token } : {}),\n ...(options.resilience !== undefined\n ? { resilience: options.resilience }\n : {}),\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n ...(options.fetchImpl !== undefined\n ? { fetchImpl: options.fetchImpl }\n : {}),\n });\n }\n\n private buildIdempotencyKey(signedXml: string): string {\n const rnc = extractTag(signedXml, 'RNCEmisor') ?? 'unknown-rnc';\n const encf = extractTag(signedXml, 'eNCF') ?? 'unknown-encf';\n return `${rnc}:${encf}:${sha256Hex(signedXml)}`;\n }\n\n private async singleFlight<T>(\n key: string,\n task: () => Promise<Result<T, DgiiError>>,\n ): Promise<Result<T, DgiiError>> {\n const existing = this.inFlight.get(key);\n if (existing) {\n return existing as Promise<Result<T, DgiiError>>;\n }\n const promise = task();\n this.inFlight.set(key, promise as Promise<Result<unknown, DgiiError>>);\n try {\n return await promise;\n } finally {\n this.inFlight.delete(key);\n }\n }\n\n /** Authenticate against DGII (or a buyer host) and store the bearer token. */\n async authenticate(\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const seed = await this.getSeed(buyerHost);\n if (seed.isErr()) {\n return err(seed.error);\n }\n if (\n typeof this.credentials.key !== 'string' ||\n typeof this.credentials.cert !== 'string'\n ) {\n return err(\n new DgiiError(\n 'A private key and certificate PEM are required to authenticate',\n { code: 'CERTIFICATE' },\n ),\n );\n }\n\n const signed = new Signature(\n this.credentials.key,\n this.credentials.cert,\n ).signXml(seed.value, 'SemillaModel');\n if (signed.isErr()) {\n return err(signed.error);\n }\n\n const token = await this.getAuthToken(signed.value, buyerHost);\n if (token.isErr()) {\n return err(token.error);\n }\n this.http.setToken(token.value.token);\n return ok(token.value);\n }\n\n private getSeed(buyerHost?: string): Promise<Result<string, DgiiError>> {\n if (buyerHost) {\n const url = buildSenderReceiverUrl(\n buyerHost,\n SenderReceiverEndpoint.Seed,\n );\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: SenderReceiverEndpoint.Seed,\n });\n }\n const url = buildUrl(this.environment, Endpoint.Seed);\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: Endpoint.Seed,\n });\n }\n\n private getAuthToken(\n signedSeed: string,\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.ValidateSeed)\n : buildUrl(this.environment, Endpoint.ValidateSeed);\n return this.http.postMultipart<AuthToken>(url, 'signed.xml', signedSeed, {\n absoluteUrl: true,\n resource: Endpoint.ValidateSeed,\n });\n }\n\n /**\n * Submit a signed e-CF. Idempotent on `RNC + eNCF + SHA-256(signed XML)`:\n * a repeated call returns the cached response instead of double-issuing.\n */\n async sendElectronicDocument(\n signedXml: string,\n fileName: string,\n buyerHost?: string,\n ): Promise<Result<InvoiceResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit: record the pending submission before the\n // network call so an interrupted send can be reconciled, not re-issued.\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.SendInvoice)\n : buildUrl(this.environment, Endpoint.SendInvoice);\n const result = await this.http.postMultipart<InvoiceResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendInvoice },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n /** Submit a signed summary invoice (RFCE). Idempotent like submissions. */\n async sendSummary(\n signedXml: string,\n fileName: string,\n ): Promise<Result<InvoiceSummaryResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceSummaryResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit (see sendElectronicDocument).\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buildUrl(this.environment, Endpoint.SendSummary, BaseUrl.CF);\n const result = await this.http.postMultipart<InvoiceSummaryResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendSummary },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n statusTrackId(\n trackId: string,\n ): Promise<Result<TrackingStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.TrackResultStatus);\n return this.http.get<TrackingStatusResponse>(\n url,\n { trackId },\n { absoluteUrl: true, resource: Endpoint.TrackResultStatus },\n );\n }\n\n inquiryStatus(\n rncEmisor: string,\n ncfElectronico: string,\n rncComprador?: string,\n codigoSeguridad?: string,\n ): Promise<Result<InquiryStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.InquiryStatus);\n return this.http.get<InquiryStatusResponse>(\n url,\n { rncEmisor, ncfElectronico, rncComprador, codigoSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryStatus },\n );\n }\n\n trackStatuses(\n rncEmisor: string,\n encf: string,\n ): Promise<Result<SummaryTrackingStatusResponse[], DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.AllTrackingEcf);\n return this.http.get<SummaryTrackingStatusResponse[]>(\n url,\n { rncEmisor, encf },\n { absoluteUrl: true, resource: Endpoint.AllTrackingEcf },\n );\n }\n\n /** Normalizes DGII's inconsistent (array | single object) directory payload. */\n async getCustomerDirectory(\n rnc: string,\n ): Promise<Result<ServiceDirectoryResponse[] | undefined, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Directory);\n const result = await this.http.get<\n ServiceDirectoryResponse[] | ServiceDirectoryResponse\n >(url, { rnc }, { absoluteUrl: true, resource: Endpoint.Directory });\n if (result.isErr()) {\n return err(result.error);\n }\n const data = result.value;\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n return ok(Array.isArray(data) ? data : [data]);\n }\n\n /** RFCE inquiry — DGII production only. */\n getSummaryInvoiceInquiry(\n rnc: string,\n encf: string,\n codSeguridad: string,\n ): Promise<Result<InquiryInvoiceSummary, DgiiError>> {\n const url = buildUrl(\n this.environment,\n Endpoint.InquiryInvoiceSummary,\n BaseUrl.CF,\n );\n return this.http.get<InquiryInvoiceSummary>(\n url,\n { rnc_emisor: rnc, encf, cod_seguridad_eCF: codSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryInvoiceSummary },\n );\n }\n\n sendCommercialApproval(\n signedXml: string,\n fileName: string,\n ): Promise<Result<CommercialApprovalResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.CommercialApproval);\n return this.http.postMultipart<CommercialApprovalResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.CommercialApproval },\n );\n }\n\n voidENCF(\n signedXml: string,\n fileName: string,\n ): Promise<Result<VoidNCFResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Void);\n return this.http.postMultipart<VoidNCFResponse>(url, fileName, signedXml, {\n absoluteUrl: true,\n resource: Endpoint.Void,\n });\n }\n}\n"],"mappings":"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","names":["Environment","Endpoint","SenderReceiverEndpoint","TrackStatusEnum","err","url"]}
1
+ {"version":3,"sources":["../src/environment.ts","../src/types.ts","../src/errors.ts","../src/result.ts","../src/resilience.ts","../src/http.ts","../src/certificate.ts","../src/signing.ts","../src/transformer.ts","../src/utils.ts","../src/client.ts"],"sourcesContent":["export enum Environment {\n /** DGII test environment */\n Dev = 'TesteCF',\n /** DGII certification environment */\n Cert = 'CerteCF',\n /** DGII production environment */\n Prod = 'eCF',\n}\n\nexport const BaseUrl = {\n /** Crédito fiscal / general e-CF services */\n ECF: 'https://ecf.dgii.gov.do',\n /** Factura de consumo (< DOP 250,000) */\n CF: 'https://fc.dgii.gov.do',\n /** DGII service status */\n STATUS: 'https://statusecf.dgii.gov.do',\n} as const;\n\nexport type BaseUrlKey = keyof typeof BaseUrl;\n\nexport enum Endpoint {\n Seed = 'Autenticacion/api/Autenticacion/Semilla',\n ValidateSeed = 'autenticacion/api/Autenticacion/ValidarSemilla',\n SendInvoice = 'recepcion/api/FacturasElectronicas',\n SendSummary = 'recepcionfc/api/recepcion/ecf',\n InquiryInvoiceSummary = 'consultarfce/api/Consultas/Consulta',\n CommercialApproval = 'aprobacionComercial/api/AprobacionComercial',\n TrackResultStatus = 'consultaresultado/api/Consultas/Estado',\n InquiryStatus = 'consultaestado/api/Consultas/Estado',\n AllTrackingEcf = 'ConsultaTrackIds/api/TrackIds/Consulta',\n Directory = 'consultadirectorio/api/consultas/obtenerdirectorioporrnc',\n Void = 'anulacionrangos/api/operaciones/anularrango',\n}\n\n/** Endpoints used when talking to a buyer's Sender↔Receiver host. */\nexport enum SenderReceiverEndpoint {\n Seed = 'fe/autenticacion/api/semilla',\n ValidateSeed = 'fe/autenticacion/api/validacioncertificado',\n SendInvoice = 'fe/recepcion/api/ecf',\n CommercialApproval = 'fe/aprobacioncomercial/api/ecf',\n}\n\n/** Build an absolute DGII URL: `${baseUrl}/${environment}/${endpoint}`. */\nexport const buildUrl = (\n environment: Environment,\n endpoint: Endpoint,\n baseUrl: string = BaseUrl.ECF,\n): string => `${baseUrl.replace(/\\/+$/, '')}/${environment}/${endpoint}`;\n\n/** Build an absolute Sender↔Receiver URL against a buyer host. */\nexport const buildSenderReceiverUrl = (\n host: string,\n endpoint: SenderReceiverEndpoint,\n): string => `${host.replace(/\\/+$/, '')}/${endpoint}`;\n","export interface Mensaje {\n valor: string;\n codigo: number;\n}\n\nexport interface AuthToken {\n token: string;\n expira: string;\n expedido: string;\n}\n\nexport enum TrackStatusEnum {\n NotFound = 'No encontrado',\n Accepted = 'Aceptado',\n Rejected = 'Rechazado',\n InProcess = 'En Proceso',\n ConditionalAccepted = 'Aceptado Condicional',\n}\n\nexport type TrackStatusCode = 0 | 1 | 2 | 3 | 4;\n\nexport interface TrackingStatusResponse {\n trackId: string;\n codigo: TrackStatusCode;\n estado: TrackStatusEnum;\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n fechaRecepcion: string;\n mensajes?: Mensaje[];\n}\n\nexport type InquiryStatusCode = 0 | 1 | 2;\n\nexport type InquiryStatus = 'No encontrado' | 'Aceptado' | 'Rechazado';\n\nexport interface InquiryStatusResponse {\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n rncEmisor?: string;\n ncfElectronico?: string;\n montoTotal?: number;\n totalITBIS?: number;\n fechaEmision?: string;\n fechaFirma?: string;\n rncComprador?: string;\n codigoSeguridad?: string;\n idExtranjero?: string;\n}\n\nexport interface SummaryTrackingStatusResponse {\n trackId: string;\n estado: string;\n fechaRecepcion: string;\n}\n\nexport interface InvoiceResponse {\n trackId?: string;\n error?: string;\n mensajes?: Mensaje[];\n}\n\nexport interface InvoiceSummaryResponse {\n codigo: number;\n estado: 'Aceptado' | 'Rechazado' | 'Aceptado Condicional';\n mensajes?: Mensaje[];\n encf: string;\n secuenciaUtilizada: boolean;\n}\n\nexport interface ServiceDirectoryResponse {\n nombre: string;\n rnc: string;\n urlRecepcion: string;\n urlAceptacion: string;\n urlOpcional: string;\n}\n\nexport interface InquiryInvoiceSummary {\n rnc: string;\n encf: string;\n secuenciaUtilizada: boolean;\n codigo: InquiryStatusCode;\n estado: InquiryStatus;\n mensajes?: Mensaje[];\n}\n\nexport interface CommercialApprovalResponse {\n codigo: '01' | '02';\n estado: 'Aprobación Comercial Aprobada.' | 'Aprobacion Comercial Rechazada.';\n mensaje: string[];\n}\n\nexport interface VoidNCFResponse {\n rnc: string;\n codigo: string;\n nombre: string;\n mensajes: string[];\n}\n","import type { Mensaje } from './types.js';\n\nexport type DgiiErrorCode =\n | 'INVALID_XML'\n | 'CERTIFICATE'\n | 'SIGNING'\n | 'HTTP'\n | 'AUTH'\n | 'TIMEOUT'\n | 'CIRCUIT_OPEN'\n | 'IDEMPOTENCY'\n | 'VALIDATION'\n | 'UNKNOWN';\n\nconst RETRYABLE_STATUSES = new Set<number>([408, 429, 500, 502, 503, 504]);\n\nexport const isRetryableStatus = (status: number | undefined): boolean =>\n status !== undefined && RETRYABLE_STATUSES.has(status);\n\nexport interface DgiiErrorOptions {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n data?: unknown;\n mensajes?: Mensaje[];\n retryable?: boolean;\n cause?: unknown;\n}\n\nconst MAX_RAW = 1000;\n\nconst truncate = (value: string): string =>\n value.length > MAX_RAW ? `${value.slice(0, MAX_RAW)}…` : value;\n\nconst collapseWhitespace = (value: string): string =>\n value.replace(/\\s+/g, ' ').trim();\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst looksLikeHtml = (value: string): boolean =>\n /^\\s*<(?:!doctype|html|body|head)\\b/i.test(value);\n\nconst stripHtml = (value: string): string =>\n collapseWhitespace(\n value\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<[^>]+>/g, ' '),\n );\n\nconst readMensajes = (value: unknown): Mensaje[] | undefined => {\n if (!Array.isArray(value) || value.length === 0) {\n return undefined;\n }\n const out: Mensaje[] = [];\n for (const item of value) {\n if (typeof item === 'string' && item.trim()) {\n out.push({ valor: item.trim(), codigo: 0 });\n } else if (isObject(item) && typeof item.valor === 'string') {\n out.push({\n valor: item.valor,\n codigo: typeof item.codigo === 'number' ? item.codigo : 0,\n });\n }\n }\n return out.length ? out : undefined;\n};\n\nconst MESSAGE_KEYS = [\n 'mensaje',\n 'Mensaje',\n 'message',\n 'Message',\n 'error',\n 'Error',\n 'errorMessage',\n 'error_description',\n 'detail',\n 'Detail',\n 'title',\n 'Title',\n 'descripcion',\n 'Descripcion',\n];\n\n/**\n * Reduce DGII's inconsistent error payloads (bare string, `{ mensajes }`,\n * ASP.NET ProblemDetails/ModelState, or an HTML page) to a single message.\n */\nexport const extractDgiiErrorMessage = (\n data: unknown,\n seen: WeakSet<object> = new WeakSet<object>(),\n): string | undefined => {\n if (data === undefined || data === null) {\n return undefined;\n }\n\n if (typeof data === 'string') {\n const trimmed = data.trim();\n if (!trimmed) {\n return undefined;\n }\n if (/^[[{\"]/.test(trimmed)) {\n try {\n return extractDgiiErrorMessage(JSON.parse(trimmed), seen);\n } catch {\n // Not JSON after all — fall through to raw text.\n }\n }\n if (looksLikeHtml(trimmed)) {\n const text = stripHtml(trimmed);\n return text ? truncate(text) : undefined;\n }\n return truncate(collapseWhitespace(trimmed));\n }\n\n if (typeof data === 'number' || typeof data === 'boolean') {\n return String(data);\n }\n\n if (data instanceof Error) {\n return data.message || undefined;\n }\n\n if (Array.isArray(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n const parts = data\n .map((item) => extractDgiiErrorMessage(item, seen))\n .filter((item): item is string => Boolean(item));\n return parts.length ? truncate(parts.join(' | ')) : undefined;\n }\n\n if (isObject(data)) {\n if (seen.has(data)) {\n return undefined;\n }\n seen.add(data);\n\n const mensajes = readMensajes(data.mensajes ?? data.Mensajes);\n if (mensajes) {\n return truncate(mensajes.map((mensaje) => mensaje.valor).join(' | '));\n }\n\n for (const key of MESSAGE_KEYS) {\n const value = data[key];\n if (typeof value === 'string' && value.trim()) {\n return truncate(collapseWhitespace(value));\n }\n if (key === 'error' && (isObject(value) || Array.isArray(value))) {\n const nested = extractDgiiErrorMessage(value, seen);\n if (nested) {\n return nested;\n }\n }\n }\n\n const errors = data.errors ?? data.Errors;\n if (isObject(errors)) {\n const parts = Object.entries(errors)\n .map(([field, value]) => {\n const nested = extractDgiiErrorMessage(value, seen);\n return nested ? `${field}: ${nested}` : undefined;\n })\n .filter((item): item is string => Boolean(item));\n if (parts.length) {\n return truncate(parts.join(' | '));\n }\n } else if (errors) {\n const nested = extractDgiiErrorMessage(errors, seen);\n if (nested) {\n return nested;\n }\n }\n\n try {\n const serialized = JSON.stringify(data);\n if (serialized && serialized !== '{}') {\n return truncate(serialized);\n }\n } catch {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport class DgiiError extends Error {\n readonly code: DgiiErrorCode;\n readonly status?: number;\n readonly statusText?: string;\n readonly resource?: string;\n readonly method?: string;\n readonly baseURL?: string;\n readonly data?: unknown;\n readonly mensajes?: Mensaje[];\n readonly retryable: boolean;\n\n constructor(message: string, options: DgiiErrorOptions = {}) {\n super(message);\n this.name = 'DgiiError';\n Object.setPrototypeOf(this, DgiiError.prototype);\n\n this.code = options.code ?? 'UNKNOWN';\n this.status = options.status;\n this.statusText = options.statusText;\n this.resource = options.resource;\n this.method = options.method;\n this.baseURL = options.baseURL;\n this.data = options.data;\n this.mensajes = options.mensajes;\n this.retryable = options.retryable ?? isRetryableStatus(options.status);\n\n if (options.cause !== undefined) {\n Object.defineProperty(this, 'cause', {\n value: options.cause,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n statusText: this.statusText,\n resource: this.resource,\n method: this.method,\n mensajes: this.mensajes,\n data: this.data,\n };\n }\n}\n\nexport interface DgiiErrorContext {\n code?: DgiiErrorCode;\n status?: number;\n statusText?: string;\n resource?: string;\n method?: string;\n baseURL?: string;\n fallbackMessage?: string;\n}\n\n/** Normalize any thrown value into a {@link DgiiError}. */\nexport const toDgiiError = (\n err: unknown,\n context: DgiiErrorContext = {},\n): DgiiError => {\n if (err instanceof DgiiError) {\n return err;\n }\n\n if (err instanceof Error) {\n return new DgiiError(\n err.message || context.fallbackMessage || 'DGII request failed',\n {\n ...context,\n cause: err,\n },\n );\n }\n\n const message =\n extractDgiiErrorMessage(err) ||\n context.fallbackMessage ||\n 'DGII request failed';\n const status =\n isObject(err) && typeof err.status === 'number'\n ? err.status\n : context.status;\n\n return new DgiiError(message, {\n ...context,\n status,\n data: err,\n mensajes: isObject(err)\n ? readMensajes(err.mensajes ?? err.Mensajes)\n : undefined,\n cause: err,\n });\n};\n","import type { Result } from 'neverthrow';\nimport type { DgiiError } from './errors.js';\n\nexport type { Result } from 'neverthrow';\n\nexport {\n Ok,\n Err,\n ok,\n err,\n okAsync,\n errAsync,\n fromThrowable,\n fromPromise,\n fromSafePromise,\n ResultAsync,\n} from 'neverthrow';\n\n/** A {@link Result} whose failure channel is always {@link DgiiError}. */\nexport type DgiiResult<T> = Result<T, DgiiError>;\n","import {\n ConsecutiveBreaker,\n ExponentialBackoff,\n TimeoutStrategy,\n bulkhead,\n circuitBreaker,\n handleAll,\n handleWhen,\n retry,\n timeout,\n wrap,\n type IPolicy,\n} from 'cockatiel';\nimport { DgiiError } from './errors.js';\n\nexport interface ResilienceOptions {\n /** Maximum number of attempts (including the first). Default 3. */\n maxRetries?: number;\n /** Consecutive failures before the circuit opens. Default 5. */\n breakerThreshold?: number;\n /** Milliseconds the circuit stays open before half-opening. Default 30s. */\n halfOpenAfterMs?: number;\n /** Per-attempt timeout in milliseconds. Default 15s. */\n timeoutMs?: number;\n /** Initial retry backoff delay in milliseconds. Default 100. */\n retryInitialDelayMs?: number;\n /** Maximum concurrent in-flight requests. Default 20. */\n bulkheadLimit?: number;\n /** Maximum queued requests while the bulkhead is saturated. Default 40. */\n bulkheadQueue?: number;\n}\n\nexport const defaultResilienceOptions: Required<ResilienceOptions> = {\n maxRetries: 3,\n breakerThreshold: 5,\n halfOpenAfterMs: 30_000,\n timeoutMs: 15_000,\n retryInitialDelayMs: 100,\n bulkheadLimit: 20,\n bulkheadQueue: 40,\n};\n\n/**\n * Only transient failures are retried: network errors, timeouts, 408, 429 and\n * 5xx. A rejected e-CF (4xx) must never be blindly re-sent.\n */\nexport const isRetryableError = (error: unknown): boolean => {\n if (error instanceof DgiiError) {\n return error.retryable;\n }\n if (error instanceof Error) {\n const name = error.name.toLowerCase();\n const message = error.message.toLowerCase();\n return (\n name === 'typeerror' ||\n name === 'aborterror' ||\n name === 'fetcherror' ||\n name === 'timeouterror' ||\n name.includes('cancel') ||\n message.includes('timeout') ||\n message.includes('aborted') ||\n message.includes('network')\n );\n }\n return false;\n};\n\nexport interface ResiliencePolicies {\n readonly retry: IPolicy;\n readonly circuitBreaker: IPolicy;\n readonly timeout: IPolicy;\n readonly bulkhead: IPolicy;\n /** Composed policy: `retry → circuitBreaker → timeout → bulkhead`. */\n readonly policy: IPolicy;\n}\n\n/** Build the composed resilience policy used by the HTTP client. */\nexport const createResiliencePolicies = (\n options: ResilienceOptions = {},\n): ResiliencePolicies => {\n const opts = { ...defaultResilienceOptions, ...options };\n\n const retryPolicy = retry(handleWhen(isRetryableError), {\n maxAttempts: opts.maxRetries,\n backoff: new ExponentialBackoff({ initialDelay: opts.retryInitialDelayMs }),\n });\n\n const breakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: opts.halfOpenAfterMs,\n breaker: new ConsecutiveBreaker(opts.breakerThreshold),\n });\n\n const timeoutPolicy = timeout(opts.timeoutMs, TimeoutStrategy.Aggressive);\n const bulkheadPolicy = bulkhead(opts.bulkheadLimit, opts.bulkheadQueue);\n\n const policy = wrap(\n retryPolicy,\n breakerPolicy,\n timeoutPolicy,\n bulkheadPolicy,\n );\n\n return {\n retry: retryPolicy,\n circuitBreaker: breakerPolicy,\n timeout: timeoutPolicy,\n bulkhead: bulkheadPolicy,\n policy,\n };\n};\n","import { err, ok, type Result } from './result.js';\nimport { DgiiError, extractDgiiErrorMessage, toDgiiError } from './errors.js';\nimport {\n createResiliencePolicies,\n type ResilienceOptions,\n type ResiliencePolicies,\n} from './resilience.js';\n\n/**\n * Pluggable idempotency store. Provide a Redis/Postgres-backed implementation\n * in production so a retried or duplicated submission never double-issues.\n */\nexport interface IdempotencyStore {\n get<T>(key: string): Promise<T | undefined>;\n set<T>(key: string, value: T): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Process-local default. Fine for single-instance usage and tests. */\nexport class InMemoryIdempotencyStore implements IdempotencyStore {\n private readonly store = new Map<string, unknown>();\n\n async get<T>(key: string): Promise<T | undefined> {\n return this.store.get(key) as T | undefined;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.store.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token?: string;\n resilience?: ResilienceOptions;\n policies?: ResiliencePolicies;\n timeoutMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST';\n /** Absolute URL when `absoluteUrl` is true, otherwise a path appended to baseUrl. */\n path: string;\n absoluteUrl?: boolean;\n headers?: Record<string, string>;\n body?: BodyInit;\n query?: Record<string, string | number | undefined>;\n resource?: string;\n}\n\ninterface RequestContext {\n method: string;\n resource: string;\n baseURL: string;\n}\n\n/** Thin HTTP client over the native `fetch`, wrapped in resilience policies. */\nexport class HttpClient {\n private token?: string;\n private readonly policies: ResiliencePolicies;\n private readonly fetchImpl: typeof fetch;\n private readonly baseUrl: string;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.token = options.token;\n this.policies =\n options.policies ??\n createResiliencePolicies({\n ...options.resilience,\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n });\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n setToken(token: string): void {\n this.token = token;\n }\n\n clearToken(): void {\n this.token = undefined;\n }\n\n private buildUrl(\n path: string,\n absoluteUrl: boolean | undefined,\n query: RequestOptions['query'],\n ): string {\n let url = absoluteUrl\n ? path\n : `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;\n\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== '') {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) {\n url += (url.includes('?') ? '&' : '?') + qs;\n }\n }\n return url;\n }\n\n private authHeaders(extra?: Record<string, string>): Record<string, string> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (this.token) {\n headers.Authorization = `Bearer ${this.token}`;\n }\n return { ...headers, ...extra };\n }\n\n private async readBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? '';\n try {\n if (contentType.includes('json')) {\n return await response.json();\n }\n const text = await response.text();\n return text.length ? text : undefined;\n } catch {\n return undefined;\n }\n }\n\n private async parseResponse<T>(\n response: Response,\n ctx: RequestContext,\n ): Promise<Result<T, DgiiError>> {\n const data = await this.readBody(response);\n\n if (response.ok) {\n return ok(data as T);\n }\n\n const message =\n extractDgiiErrorMessage(data) ??\n `DGII request failed with status ${response.status}`;\n const error = new DgiiError(message, {\n code: response.status === 401 ? 'AUTH' : 'HTTP',\n status: response.status,\n statusText: response.statusText,\n resource: ctx.resource,\n method: ctx.method,\n baseURL: ctx.baseURL,\n data,\n });\n\n // Throw retryable failures so the retry/breaker policies can act on them;\n // non-retryable client errors are returned as a typed failure.\n if (error.retryable) {\n throw error;\n }\n return err(error);\n }\n\n async request<T>(options: RequestOptions): Promise<Result<T, DgiiError>> {\n const url = this.buildUrl(options.path, options.absoluteUrl, options.query);\n const method = options.method ?? 'GET';\n const headers = this.authHeaders(options.headers);\n const ctx: RequestContext = {\n method,\n resource: options.resource ?? options.path,\n baseURL: this.baseUrl,\n };\n\n try {\n return await this.policies.policy.execute(async ({ signal }) => {\n const response = await this.fetchImpl(url, {\n method,\n headers,\n body: options.body,\n signal,\n });\n return this.parseResponse<T>(response, ctx);\n });\n } catch (error) {\n return err(toDgiiError(error, ctx));\n }\n }\n\n get<T>(\n path: string,\n query?: RequestOptions['query'],\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n return this.request<T>({\n method: 'GET',\n path,\n query,\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n\n /**\n * POST a signed XML as a multipart `xml` file part. The runtime computes\n * `Content-Length` from the Blob — never set it manually.\n */\n postMultipart<T>(\n path: string,\n fileName: string,\n xml: string,\n opts?: { absoluteUrl?: boolean; resource?: string },\n ): Promise<Result<T, DgiiError>> {\n const form = new FormData();\n form.append('xml', new Blob([xml], { type: 'application/xml' }), fileName);\n return this.request<T>({\n method: 'POST',\n path,\n body: form,\n headers: { Accept: 'application/json' },\n absoluteUrl: opts?.absoluteUrl,\n resource: opts?.resource,\n });\n }\n}\n","import { readFileSync } from 'node:fs';\nimport forge from 'node-forge';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport interface P12ReaderData {\n key?: string;\n cert?: string;\n publicKey?: string;\n}\n\nexport interface CertificateInfo {\n subject: string;\n issuer: string;\n validFrom: Date;\n validTo: Date;\n serialNumber: string;\n}\n\nconst asErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\n/** Reads a PKCS#12 (.p12) bundle and extracts the private key + certificate. */\nexport class P12Reader {\n constructor(private readonly passphrase: string) {}\n\n private load(base64: string): forge.pkcs12.Pkcs12Pfx {\n const der = forge.util.decode64(base64);\n const asn1 = forge.asn1.fromDer(der);\n return forge.pkcs12.pkcs12FromAsn1(asn1, false, this.passphrase);\n }\n\n private extractKey(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n // DGII bundles normally carry a shrouded (encrypted) PKCS#8 key bag, but\n // unencrypted bundles use a plain keyBag. A certBag never holds a private\n // key, so it must not be used as a fallback.\n const keyBagTypes = [\n forge.pki.oids.pkcs8ShroudedKeyBag,\n forge.pki.oids.keyBag,\n ];\n for (const bagType of keyBagTypes) {\n const bag = p12.getBags({ bagType })[bagType]?.[0];\n if (bag?.key) {\n return forge.pki.privateKeyToPem(bag.key);\n }\n }\n return undefined;\n }\n\n private extractCertificate(p12: forge.pkcs12.Pkcs12Pfx): string | undefined {\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag });\n const certBag = certBags[forge.pki.oids.certBag]?.[0];\n if (!certBag?.cert) {\n return undefined;\n }\n return forge.pki.certificateToPem(certBag.cert);\n }\n\n getKeyFromFile(fileName: string): Result<P12ReaderData, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getKeyFromStringBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getKeyFromStringBase64(base64: string): Result<P12ReaderData, DgiiError> {\n try {\n const p12 = this.load(base64);\n const key = this.extractKey(p12);\n const cert = this.extractCertificate(p12);\n if (!key || !cert) {\n return err(\n new DgiiError('PKCS#12 must contain a private key and certificate', {\n code: 'CERTIFICATE',\n }),\n );\n }\n const publicKey = forge.pki.publicKeyToPem(\n forge.pki.certificateFromPem(cert).publicKey,\n );\n return ok({ key, cert, publicKey });\n } catch (error) {\n return err(\n new DgiiError(`Unable to parse .p12: ${asErrorMessage(error)}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n private toCertificateInfo(certPem: string): CertificateInfo {\n const certificate = forge.pki.certificateFromPem(certPem);\n return {\n subject: certificate.subject.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n issuer: certificate.issuer.attributes\n .map((attribute) => `${attribute.shortName}=${attribute.value}`)\n .join(', '),\n validFrom: certificate.validity.notBefore,\n validTo: certificate.validity.notAfter,\n serialNumber: certificate.serialNumber,\n };\n }\n\n getCertificateInfo(fileName: string): Result<CertificateInfo, DgiiError> {\n try {\n const base64 = readFileSync(fileName, 'base64');\n return this.getCertificateInfoFromBase64(base64);\n } catch (error) {\n return err(\n new DgiiError(`Unable to read .p12 file: ${fileName}`, {\n code: 'CERTIFICATE',\n cause: error,\n }),\n );\n }\n }\n\n getCertificateInfoFromBase64(\n base64: string,\n ): Result<CertificateInfo, DgiiError> {\n try {\n const certPem = this.extractCertificate(this.load(base64));\n if (!certPem) {\n return err(\n new DgiiError('Certificate not found in PKCS#12', {\n code: 'CERTIFICATE',\n }),\n );\n }\n return ok(this.toCertificateInfo(certPem));\n } catch (error) {\n return err(\n new DgiiError(\n `Unable to extract certificate info: ${asErrorMessage(error)}`,\n { code: 'CERTIFICATE', cause: error },\n ),\n );\n }\n }\n}\n","import crypto from 'node:crypto';\nimport { DOMParser } from '@xmldom/xmldom';\nimport { C14nCanonicalization, SignedXml } from 'xml-crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nexport type DgiiDocumentType =\n 'SemillaModel' | 'ECF' | 'RFCE' | 'ARECF' | 'ACECF' | 'ANECF' | (string & {});\n\nconst C14N_INCLUSIVE = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';\nconst RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';\nconst SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';\nconst ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature';\n/**\n * Custom digest URI: DGII hashes the inclusive C14N 1.0 form of the referenced\n * document. xml-crypto's built-in SHA-256 hashes its raw serialization, so we\n * register a digest backed by xml-crypto's inclusive C14N implementation.\n */\nconst CUSTOM_DIGEST_URI = 'http://dgii.gov.do/digest/sha256-c14n';\n\ninterface XmldomDocument extends Document {\n childNodes: NodeListOf<ChildNode>;\n}\n\n/**\n * DGII-compatible digest: hash the inclusive C14N 1.0 form of the referenced\n * document — the exact bytes a .NET/DGII verifier computes.\n */\nclass DgiiDigest {\n getHash(xml: string): string {\n const doc = new DOMParser().parseFromString(\n xml,\n ) as unknown as XmldomDocument;\n const canonical = new C14nCanonicalization().process(\n doc as unknown as Node,\n {},\n );\n return crypto\n .createHash('sha256')\n .update(canonical, 'utf8')\n .digest('base64');\n }\n\n getAlgorithmName(): string {\n return SHA256;\n }\n}\n\ninterface StrictParseResult {\n doc: XmldomDocument;\n rootName: string;\n}\n\nconst parseStrict = (xml: string): StrictParseResult => {\n const errors: string[] = [];\n const doc = new DOMParser({\n errorHandler: {\n warning: () => undefined,\n error: (message: string) => errors.push(message),\n fatalError: (message: string) => errors.push(message),\n },\n }).parseFromString(xml, 'text/xml') as unknown as XmldomDocument;\n\n if (errors.length) {\n throw new Error(`Invalid XML: ${errors.join('; ')}`);\n }\n const root = doc.documentElement;\n if (!root) {\n throw new Error('Unable to parse XML or find root element');\n }\n if (root.nodeName === 'parsererror' || root.localName === 'parsererror') {\n throw new Error(`Invalid XML: ${root.textContent ?? 'parse error'}`);\n }\n return {\n doc,\n rootName: root.localName ?? root.nodeName,\n };\n};\n\n/** Remove whitespace-only text nodes and comments before canonicalization. */\nconst cleanNodes = (node: Node): void => {\n for (let index = 0; index < node.childNodes.length; index += 1) {\n const child = node.childNodes[index];\n if (!child) {\n continue;\n }\n const isComment = child.nodeType === 8;\n const isWhitespace =\n child.nodeType === 3 && !/\\S/.test(child.nodeValue ?? '');\n if (isComment || isWhitespace) {\n node.removeChild(child);\n index -= 1;\n } else if (child.nodeType === 1) {\n cleanNodes(child);\n }\n }\n};\n\n/** Signs DGII XML documents with XMLDSig (enveloped, inclusive C14N, RSA-SHA256). */\nexport class Signature {\n constructor(\n private readonly privateKey: string,\n private readonly certificatePem: string,\n ) {}\n\n signXml(\n xml: string,\n rootElName?: DgiiDocumentType,\n ): Result<string, DgiiError> {\n let parsed: StrictParseResult;\n try {\n parsed = parseStrict(xml);\n } catch (error) {\n // Malformed input is an INVALID_XML error, not a signing failure —\n // aligning with the Python SDK.\n return err(\n new DgiiError(\n error instanceof Error\n ? error.message\n : `Invalid XML: ${String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n\n try {\n const { doc, rootName } = parsed;\n const elementName = rootElName ?? rootName;\n\n const sig = new SignedXml({\n privateKey: this.privateKey,\n publicCert: this.certificatePem,\n signatureAlgorithm: RSA_SHA256,\n canonicalizationAlgorithm: C14N_INCLUSIVE,\n });\n\n const hashAlgorithms = (\n sig as unknown as {\n HashAlgorithms: Record<string, unknown>;\n }\n ).HashAlgorithms;\n hashAlgorithms[CUSTOM_DIGEST_URI] = DgiiDigest;\n\n sig.addReference({\n xpath: `//*[local-name(.)='${elementName}']`,\n transforms: [ENVELOPED],\n digestAlgorithm: CUSTOM_DIGEST_URI,\n isEmptyUri: true,\n } as unknown as Parameters<SignedXml['addReference']>[0]);\n\n cleanNodes(doc as unknown as Node);\n sig.computeSignature(doc.toString());\n return ok(sig.getSignedXml());\n } catch (error) {\n return err(\n new DgiiError(\n `Failed to sign XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'SIGNING', cause: error },\n ),\n );\n }\n }\n}\n\nexport interface XmlCertificateValidation {\n isValid: boolean;\n subject?: string;\n issuer?: string;\n validFrom?: string;\n validTo?: string;\n error?: string;\n}\n\n/**\n * Matches `<X509Certificate>` with or without a namespace prefix (`ds:`).\n */\nconst X509_CERTIFICATE_RE =\n /<(?:[\\w]+:)?X509Certificate>([\\s\\S]*?)<\\/(?:[\\w]+:)?X509Certificate>/;\n\n/** Validate the embedded X509 certificate of a signed XML document. */\nexport const validateXMLCertificate = (\n xml: string,\n): XmlCertificateValidation => {\n try {\n const match = xml.match(X509_CERTIFICATE_RE);\n if (!match?.[1]) {\n return { isValid: false, error: 'X509Certificate not found' };\n }\n const der = Buffer.from(match[1].replace(/\\s+/g, ''), 'base64');\n const certificate = new crypto.X509Certificate(der);\n const notBefore = new Date(certificate.validFrom).getTime();\n const notAfter = new Date(certificate.validTo).getTime();\n const now = Date.now();\n const isValid = now >= notBefore && now <= notAfter;\n return {\n isValid,\n subject: certificate.subject,\n issuer: certificate.issuer,\n validFrom: certificate.validFrom,\n validTo: certificate.validTo,\n error: isValid ? undefined : 'Certificate expired or not yet valid',\n };\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n};\n","import convert from 'xml-js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\n\nconst MONETARY_RE = /^(-?)(\\d+)\\.(\\d+)$/;\n\n/** Increment a string of decimal digits (\"267\" -> \"268\", \"999\" -> \"1000\"). */\nconst incrementDigits = (digits: string): string => {\n const chars = digits.split('');\n let index = chars.length - 1;\n while (index >= 0) {\n const current = chars[index];\n if (current === '9') {\n chars[index] = '0';\n index -= 1;\n continue;\n }\n chars[index] = String(Number(current) + 1);\n return chars.join('');\n }\n return `1${chars.join('')}`;\n};\n\n/**\n * Round a decimal string to 2 places with ROUND_HALF_UP semantics.\n *\n * `Number.prototype.toFixed` cannot be used: `(2.675).toFixed(2)` is `'2.67'`\n * because the literal is not representable in binary floating point. DGII\n * expects the decimal, half-up result (`'2.68'`) — the same contract as the\n * Python SDK's `Decimal.quantize(..., rounding=ROUND_HALF_UP)`.\n *\n * Values that are not plain decimals (e.g. `1.0e3`) are returned unchanged.\n */\nexport const roundHalfUpToCents = (value: string): string => {\n const match = MONETARY_RE.exec(value);\n if (!match) {\n return value;\n }\n const sign = match[1] === '-' ? '-' : '';\n const integerPart = (match[2] ?? '0').replace(/^0+(?=\\d)/, '');\n const fractionPart = `${match[3] ?? ''}000`;\n const cents = `${integerPart}${fractionPart.slice(0, 2)}`;\n const rounded = fractionPart[2] >= '5' ? incrementDigits(cents) : cents;\n const padded = rounded.padStart(3, '0');\n return `${sign}${padded.slice(0, -2)}.${padded.slice(-2)}`;\n};\n\n/**\n * Converts between the DGII XML documents and the \"compact\" JSON shape used by\n * `xml-js` (a dict key is an element, an array is a repeated element, and\n * `_attributes` / `_text` carry attributes and text).\n */\nexport class Transformer {\n json2xml(dataObject: object, round = false): Result<string, DgiiError> {\n try {\n const data: Record<string, unknown> = {\n _declaration: { _attributes: { version: '1.0', encoding: 'utf-8' } },\n ...dataObject,\n };\n\n const xml = convert.js2xml(data as convert.ElementCompact, {\n compact: true,\n ignoreComment: true,\n spaces: 2,\n fullTagEmptyElement: true,\n textFn: (value: string, label: string) => {\n if (round && label.toLowerCase() !== 'version') {\n return roundHalfUpToCents(value);\n }\n return value;\n },\n });\n\n return ok(xml);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting JSON to XML: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n\n xml2json<T>(xml: string): Result<T, DgiiError> {\n try {\n const json = convert.xml2js(xml, {\n compact: true,\n ignoreComment: true,\n nativeType: false,\n });\n return ok(json as T);\n } catch (error) {\n return err(\n new DgiiError(\n `Error converting XML to JSON: ${error instanceof Error ? error.message : String(error)}`,\n { code: 'INVALID_XML', cause: error },\n ),\n );\n }\n }\n}\n","import { BaseUrl, Environment } from './environment.js';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport { Transformer } from './transformer.js';\n\n/**\n * Matches `<SignatureValue>` with or without a namespace prefix (`ds:`), which\n * is how .NET and other XMLDSig implementations emit the signature.\n */\nconst SIGNATURE_VALUE_RE =\n /<(?:[\\w]+:)?SignatureValue>([\\s\\S]*?)<\\/(?:[\\w]+:)?SignatureValue>/;\n\n/** First 6 chars of the `<SignatureValue>` (DGII security code). */\nexport const getCodeSixDigitfromSignature = (\n signedXml: string,\n): Result<string, DgiiError> => {\n const match = signedXml.match(SIGNATURE_VALUE_RE);\n const value = match?.[1]?.trim();\n if (!value) {\n return err(new DgiiError('SignatureValue not found', { code: 'SIGNING' }));\n }\n if (value.length < 6) {\n return err(\n new DgiiError('SignatureValue is too short', { code: 'SIGNING' }),\n );\n }\n return ok(value.slice(0, 6));\n};\n\n/** QR URL for a factura de consumo (FC). */\nexport const generateFcQRCodeURL = (\n rncemisor: string,\n encf: string,\n montototal: number,\n codigoseguridad: string,\n env: Environment,\n): string =>\n `${BaseUrl.CF}/${env.toLowerCase()}/consultatimbrefc?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&encf=${encodeURIComponent(encf)}&montototal=${encodeURIComponent(\n String(montototal),\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n\n/** QR URL for a crédito fiscal (e-CF). */\nexport const generateEcfQRCodeURL = (\n rncemisor: string,\n rncComprador: string,\n encf: string,\n montototal: string,\n fechaEmision: string,\n fechaFirma: string,\n codigoseguridad: string,\n env: Environment,\n): string => {\n let rncCompradorParam = '';\n if (rncComprador && !/E43/i.test(encf) && !/E47/i.test(encf)) {\n rncCompradorParam = `RncComprador=${encodeURIComponent(rncComprador)}&`;\n }\n return `${BaseUrl.ECF}/${env.toLowerCase()}/consultatimbre?rncemisor=${encodeURIComponent(\n rncemisor,\n )}&${rncCompradorParam}encf=${encodeURIComponent(\n encf,\n )}&fechaemision=${encodeURIComponent(\n fechaEmision,\n )}&montototal=${encodeURIComponent(\n montototal,\n )}&fechafirma=${encodeURIComponent(\n fechaFirma,\n )}&codigoseguridad=${encodeURIComponent(codigoseguridad)}`;\n};\n\nconst formatInSantoDomingo = (date: Date, withTime: boolean): string => {\n const parts = new Intl.DateTimeFormat('es-DO', {\n timeZone: 'America/Santo_Domingo',\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n ...(withTime\n ? { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }\n : {}),\n })\n .formatToParts(date)\n .reduce<Record<string, string>>((acc, part) => {\n acc[part.type] = part.value;\n return acc;\n }, {});\n\n const datePart = `${parts.day}-${parts.month}-${parts.year}`;\n return withTime\n ? `${datePart} ${parts.hour}:${parts.minute}:${parts.second}`\n : datePart;\n};\n\n/** `DD-MM-YYYY HH:mm:ss` in America/Santo_Domingo. */\nexport const getCurrentFormattedDateTime = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, true);\n\n/** `DD-MM-YYYY` in America/Santo_Domingo. */\nexport const getCurrentFormattedDate = (date: Date = new Date()): string =>\n formatInSantoDomingo(date, false);\n\n/** Extract the XML payload embedded in a DGII commercial-approval body. */\nexport const getXmlFromBodyResponse = (\n body: string,\n lastTagName = 'ACECF',\n): string | undefined =>\n body.match(new RegExp(`<\\\\?xml[\\\\s\\\\S]*?<\\\\/${lastTagName}>`))?.[0];\n\ninterface CompactElement {\n _text?: string;\n [key: string]: unknown;\n}\n\ninterface ImpuestoAdicional {\n TipoImpuesto?: CompactElement;\n MontoImpuestoSelectivoConsumoEspecifico?: CompactElement;\n MontoImpuestoSelectivoConsumoAdvalorem?: CompactElement;\n OtrosImpuestosAdicionales?: CompactElement;\n}\n\ninterface EcfTotales {\n MontoGravadoTotal?: CompactElement;\n MontoGravadoI1?: CompactElement;\n MontoGravadoI2?: CompactElement;\n MontoGravadoI3?: CompactElement;\n MontoExento?: CompactElement;\n TotalITBIS?: CompactElement;\n TotalITBIS1?: CompactElement;\n TotalITBIS2?: CompactElement;\n TotalITBIS3?: CompactElement;\n MontoImpuestoAdicional?: CompactElement;\n ImpuestosAdicionales?: {\n ImpuestoAdicional?: ImpuestoAdicional | ImpuestoAdicional[];\n };\n MontoTotal?: CompactElement;\n MontoNoFacturable?: CompactElement;\n MontoPeriodo?: CompactElement;\n}\n\ninterface EcfJson {\n ECF: {\n Encabezado?: {\n Version?: CompactElement;\n IdDoc?: {\n TipoeCF?: CompactElement;\n eNCF?: CompactElement;\n TipoIngresos?: CompactElement;\n TipoPago?: CompactElement;\n TablaFormasPago?: CompactElement;\n };\n Emisor?: {\n RNCEmisor?: CompactElement;\n RazonSocialEmisor?: CompactElement;\n FechaEmision?: CompactElement;\n };\n Comprador?: {\n RNCComprador?: CompactElement;\n IdentificadorExtranjero?: CompactElement;\n RazonSocialComprador?: CompactElement;\n };\n Totales?: EcfTotales;\n };\n };\n}\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (value === undefined || value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n};\n\nconst isEmptyObject = (value: unknown): boolean =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value as Record<string, unknown>).length === 0;\n\nconst removeEmptyValues = (input: unknown): unknown => {\n if (input === null || input === undefined || input === '') {\n return undefined;\n }\n if (Array.isArray(input)) {\n const filtered = input\n .map(removeEmptyValues)\n .filter(\n (item) =>\n item !== null &&\n item !== undefined &&\n item !== '' &&\n !isEmptyObject(item),\n );\n return filtered.length ? filtered : undefined;\n }\n if (typeof input === 'object') {\n const output: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(\n input as Record<string, unknown>,\n )) {\n const cleaned = removeEmptyValues(value);\n if (cleaned !== undefined && cleaned !== '' && !isEmptyObject(cleaned)) {\n output[key] = cleaned;\n }\n }\n return Object.keys(output).length ? output : undefined;\n }\n return input;\n};\n\n/**\n * Build the RFCE (summary invoice) document from a signed ECF-32 document.\n * Returns the unsigned RFCE XML plus the 6-digit security code.\n */\nexport const convertECF32ToRFCE = (\n ecf32Xml: string,\n): Result<{ xml: string; securityCode: string }, DgiiError> => {\n const securityCode = getCodeSixDigitfromSignature(ecf32Xml);\n if (securityCode.isErr()) {\n return err(securityCode.error);\n }\n\n const transformer = new Transformer();\n const parsed = transformer.xml2json<EcfJson>(ecf32Xml);\n if (parsed.isErr()) {\n return err(parsed.error);\n }\n\n const encabezado = parsed.value.ECF.Encabezado;\n const impuestos = toArray(\n encabezado?.Totales?.ImpuestosAdicionales?.ImpuestoAdicional,\n );\n\n const rfce = removeEmptyValues({\n RFCE: {\n Encabezado: {\n Version: encabezado?.Version,\n IdDoc: {\n TipoeCF: encabezado?.IdDoc?.TipoeCF,\n eNCF: encabezado?.IdDoc?.eNCF,\n TipoIngresos: encabezado?.IdDoc?.TipoIngresos,\n TipoPago: encabezado?.IdDoc?.TipoPago,\n TablaFormasPago: encabezado?.IdDoc?.TablaFormasPago,\n },\n Emisor: {\n RNCEmisor: encabezado?.Emisor?.RNCEmisor,\n RazonSocialEmisor: encabezado?.Emisor?.RazonSocialEmisor,\n FechaEmision: encabezado?.Emisor?.FechaEmision,\n },\n Comprador: {\n RNCComprador: encabezado?.Comprador?.RNCComprador,\n IdentificadorExtranjero:\n encabezado?.Comprador?.IdentificadorExtranjero,\n RazonSocialComprador: encabezado?.Comprador?.RazonSocialComprador,\n },\n Totales: {\n MontoGravadoTotal: encabezado?.Totales?.MontoGravadoTotal,\n MontoGravadoI1: encabezado?.Totales?.MontoGravadoI1,\n MontoGravadoI2: encabezado?.Totales?.MontoGravadoI2,\n MontoGravadoI3: encabezado?.Totales?.MontoGravadoI3,\n MontoExento: encabezado?.Totales?.MontoExento,\n TotalITBIS: encabezado?.Totales?.TotalITBIS,\n TotalITBIS1: encabezado?.Totales?.TotalITBIS1,\n TotalITBIS2: encabezado?.Totales?.TotalITBIS2,\n TotalITBIS3: encabezado?.Totales?.TotalITBIS3,\n MontoImpuestoAdicional: encabezado?.Totales?.MontoImpuestoAdicional,\n ImpuestosAdicionales: {\n ImpuestoAdicional: impuestos.map((impuesto) => ({\n TipoImpuesto: impuesto.TipoImpuesto,\n MontoImpuestoSelectivoConsumoEspecifico:\n impuesto.MontoImpuestoSelectivoConsumoEspecifico,\n MontoImpuestoSelectivoConsumoAdvalorem:\n impuesto.MontoImpuestoSelectivoConsumoAdvalorem,\n OtrosImpuestosAdicionales: impuesto.OtrosImpuestosAdicionales,\n })),\n },\n MontoTotal: encabezado?.Totales?.MontoTotal,\n MontoNoFacturable: encabezado?.Totales?.MontoNoFacturable,\n MontoPeriodo: encabezado?.Totales?.MontoPeriodo,\n },\n CodigoSeguridadeCF: securityCode.value,\n },\n },\n });\n\n if (typeof rfce !== 'object' || rfce === null) {\n return err(\n new DgiiError('Unable to build RFCE document', { code: 'VALIDATION' }),\n );\n }\n\n const xml = transformer.json2xml(rfce);\n if (xml.isErr()) {\n return err(xml.error);\n }\n\n return ok({ xml: xml.value, securityCode: securityCode.value });\n};\n","import { createHash } from 'node:crypto';\nimport { err, ok, type Result } from './result.js';\nimport { DgiiError } from './errors.js';\nimport {\n BaseUrl,\n Endpoint,\n Environment,\n SenderReceiverEndpoint,\n buildSenderReceiverUrl,\n buildUrl,\n} from './environment.js';\nimport {\n HttpClient,\n InMemoryIdempotencyStore,\n type IdempotencyStore,\n} from './http.js';\nimport type { ResilienceOptions } from './resilience.js';\nimport { Signature } from './signing.js';\nimport type { P12ReaderData } from './certificate.js';\nimport type {\n AuthToken,\n CommercialApprovalResponse,\n InquiryInvoiceSummary,\n InquiryStatusResponse,\n InvoiceResponse,\n InvoiceSummaryResponse,\n ServiceDirectoryResponse,\n SummaryTrackingStatusResponse,\n TrackingStatusResponse,\n VoidNCFResponse,\n} from './types.js';\n\nexport interface EcfOptions {\n /** Pre-existing bearer token (skips the authentication round-trip). */\n token?: string;\n /** Pluggable idempotency store; defaults to an in-memory store. */\n idempotencyStore?: IdempotencyStore;\n resilience?: ResilienceOptions;\n timeoutMs?: number;\n /** Injectable fetch (useful for tests). */\n fetchImpl?: typeof fetch;\n}\n\ninterface PendingSubmission {\n readonly pending: true;\n}\n\nconst PENDING_SUBMISSION: PendingSubmission = { pending: true };\n\nconst isPendingSubmission = (value: unknown): value is PendingSubmission =>\n typeof value === 'object' &&\n value !== null &&\n (value as { pending?: unknown }).pending === true;\n\nconst sha256Hex = (value: string): string =>\n createHash('sha256').update(value, 'utf8').digest('hex');\n\nconst extractTag = (xml: string, tag: string): string | undefined => {\n const match = xml.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));\n return match?.[1]?.trim();\n};\n\n/**\n * DGII e-CF client. Every method returns a `Result` — no thrown domain errors.\n */\nexport class ECF {\n private readonly environment: Environment;\n private readonly http: HttpClient;\n private readonly idempotency: IdempotencyStore;\n private readonly credentials: P12ReaderData;\n private readonly inFlight = new Map<\n string,\n Promise<Result<unknown, DgiiError>>\n >();\n\n constructor(\n credentials: P12ReaderData,\n environment: Environment = Environment.Dev,\n options: EcfOptions = {},\n ) {\n this.credentials = credentials;\n this.environment = environment;\n this.idempotency =\n options.idempotencyStore ?? new InMemoryIdempotencyStore();\n this.http = new HttpClient({\n baseUrl: BaseUrl.ECF,\n ...(options.token !== undefined ? { token: options.token } : {}),\n ...(options.resilience !== undefined\n ? { resilience: options.resilience }\n : {}),\n ...(options.timeoutMs !== undefined\n ? { timeoutMs: options.timeoutMs }\n : {}),\n ...(options.fetchImpl !== undefined\n ? { fetchImpl: options.fetchImpl }\n : {}),\n });\n }\n\n private buildIdempotencyKey(signedXml: string): string {\n const rnc = extractTag(signedXml, 'RNCEmisor') ?? 'unknown-rnc';\n const encf = extractTag(signedXml, 'eNCF') ?? 'unknown-encf';\n return `${rnc}:${encf}:${sha256Hex(signedXml)}`;\n }\n\n private async singleFlight<T>(\n key: string,\n task: () => Promise<Result<T, DgiiError>>,\n ): Promise<Result<T, DgiiError>> {\n const existing = this.inFlight.get(key);\n if (existing) {\n return existing as Promise<Result<T, DgiiError>>;\n }\n const promise = task();\n this.inFlight.set(key, promise as Promise<Result<unknown, DgiiError>>);\n try {\n return await promise;\n } finally {\n this.inFlight.delete(key);\n }\n }\n\n /** Authenticate against DGII (or a buyer host) and store the bearer token. */\n async authenticate(\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const seed = await this.getSeed(buyerHost);\n if (seed.isErr()) {\n return err(seed.error);\n }\n if (\n typeof this.credentials.key !== 'string' ||\n typeof this.credentials.cert !== 'string'\n ) {\n return err(\n new DgiiError(\n 'A private key and certificate PEM are required to authenticate',\n { code: 'CERTIFICATE' },\n ),\n );\n }\n\n const signed = new Signature(\n this.credentials.key,\n this.credentials.cert,\n ).signXml(seed.value, 'SemillaModel');\n if (signed.isErr()) {\n return err(signed.error);\n }\n\n const token = await this.getAuthToken(signed.value, buyerHost);\n if (token.isErr()) {\n return err(token.error);\n }\n this.http.setToken(token.value.token);\n return ok(token.value);\n }\n\n private getSeed(buyerHost?: string): Promise<Result<string, DgiiError>> {\n if (buyerHost) {\n const url = buildSenderReceiverUrl(\n buyerHost,\n SenderReceiverEndpoint.Seed,\n );\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: SenderReceiverEndpoint.Seed,\n });\n }\n const url = buildUrl(this.environment, Endpoint.Seed);\n return this.http.get<string>(url, undefined, {\n absoluteUrl: true,\n resource: Endpoint.Seed,\n });\n }\n\n private getAuthToken(\n signedSeed: string,\n buyerHost?: string,\n ): Promise<Result<AuthToken, DgiiError>> {\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.ValidateSeed)\n : buildUrl(this.environment, Endpoint.ValidateSeed);\n return this.http.postMultipart<AuthToken>(url, 'signed.xml', signedSeed, {\n absoluteUrl: true,\n resource: Endpoint.ValidateSeed,\n });\n }\n\n /**\n * Submit a signed e-CF. Idempotent on `RNC + eNCF + SHA-256(signed XML)`:\n * a repeated call returns the cached response instead of double-issuing.\n */\n async sendElectronicDocument(\n signedXml: string,\n fileName: string,\n buyerHost?: string,\n ): Promise<Result<InvoiceResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit: record the pending submission before the\n // network call so an interrupted send can be reconciled, not re-issued.\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.SendInvoice)\n : buildUrl(this.environment, Endpoint.SendInvoice);\n const result = await this.http.postMultipart<InvoiceResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendInvoice },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n /** Submit a signed summary invoice (RFCE). Idempotent like submissions. */\n async sendSummary(\n signedXml: string,\n fileName: string,\n ): Promise<Result<InvoiceSummaryResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n const cached = await this.idempotency.get<\n InvoiceSummaryResponse | PendingSubmission\n >(key);\n if (cached !== undefined) {\n if (isPendingSubmission(cached)) {\n return err(\n new DgiiError(\n 'A submission with this key is already pending; reconcile via a status lookup before retrying',\n { code: 'IDEMPOTENCY' },\n ),\n );\n }\n return ok(cached);\n }\n return this.singleFlight(key, async () => {\n // Persist-before-transmit (see sendElectronicDocument).\n await this.idempotency.set(key, PENDING_SUBMISSION);\n const url = buildUrl(this.environment, Endpoint.SendSummary, BaseUrl.CF);\n const result = await this.http.postMultipart<InvoiceSummaryResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendSummary },\n );\n if (result.isOk()) {\n await this.idempotency.set(key, result.value);\n } else {\n await this.idempotency.delete(key);\n }\n return result;\n });\n }\n\n statusTrackId(\n trackId: string,\n ): Promise<Result<TrackingStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.TrackResultStatus);\n return this.http.get<TrackingStatusResponse>(\n url,\n { trackId },\n { absoluteUrl: true, resource: Endpoint.TrackResultStatus },\n );\n }\n\n inquiryStatus(\n rncEmisor: string,\n ncfElectronico: string,\n rncComprador?: string,\n codigoSeguridad?: string,\n ): Promise<Result<InquiryStatusResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.InquiryStatus);\n return this.http.get<InquiryStatusResponse>(\n url,\n { rncEmisor, ncfElectronico, rncComprador, codigoSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryStatus },\n );\n }\n\n trackStatuses(\n rncEmisor: string,\n encf: string,\n ): Promise<Result<SummaryTrackingStatusResponse[], DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.AllTrackingEcf);\n return this.http.get<SummaryTrackingStatusResponse[]>(\n url,\n { rncEmisor, encf },\n { absoluteUrl: true, resource: Endpoint.AllTrackingEcf },\n );\n }\n\n /** Normalizes DGII's inconsistent (array | single object) directory payload. */\n async getCustomerDirectory(\n rnc: string,\n ): Promise<Result<ServiceDirectoryResponse[] | undefined, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Directory);\n const result = await this.http.get<\n ServiceDirectoryResponse[] | ServiceDirectoryResponse\n >(url, { rnc }, { absoluteUrl: true, resource: Endpoint.Directory });\n if (result.isErr()) {\n return err(result.error);\n }\n const data = result.value;\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n return ok(Array.isArray(data) ? data : [data]);\n }\n\n /** RFCE inquiry — DGII production only. */\n async getSummaryInvoiceInquiry(\n rnc: string,\n encf: string,\n codSeguridad: string,\n ): Promise<Result<InquiryInvoiceSummary, DgiiError>> {\n if (this.environment !== Environment.Prod) {\n return err(\n new DgiiError(\n `getSummaryInvoiceInquiry is only available in the production environment (eCF); current environment is ${this.environment}`,\n { code: 'VALIDATION' },\n ),\n );\n }\n const url = buildUrl(\n this.environment,\n Endpoint.InquiryInvoiceSummary,\n BaseUrl.CF,\n );\n return this.http.get<InquiryInvoiceSummary>(\n url,\n { rnc_emisor: rnc, encf, cod_seguridad_eCF: codSeguridad },\n { absoluteUrl: true, resource: Endpoint.InquiryInvoiceSummary },\n );\n }\n\n sendCommercialApproval(\n signedXml: string,\n fileName: string,\n ): Promise<Result<CommercialApprovalResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.CommercialApproval);\n return this.http.postMultipart<CommercialApprovalResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.CommercialApproval },\n );\n }\n\n voidENCF(\n signedXml: string,\n fileName: string,\n ): Promise<Result<VoidNCFResponse, DgiiError>> {\n const url = buildUrl(this.environment, Endpoint.Void);\n return this.http.postMultipart<VoidNCFResponse>(url, fileName, signedXml, {\n absoluteUrl: true,\n resource: Endpoint.Void,\n });\n }\n}\n"],"mappings":"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","names":["Environment","Endpoint","SenderReceiverEndpoint","TrackStatusEnum","err","url"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deuriib/dgii-ecf",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "DGII e-CF electronic invoicing SDK for the Dominican Republic — authenticate, sign (XMLDSig/C14N) and transmit electronic tax documents. Bun-first, native fetch, result-pattern.",
5
5
  "type": "module",
6
6
  "license": "MIT",