@deuriib/dgii-ecf 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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/xml.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 /**\n * Synchronous acknowledgement text. DGII sends this as a singular string on\n * the general reception endpoint (`recepcion/api/FacturasElectronicas`).\n */\n mensaje?: string;\n /** Tolerated array form used by the RFCE and status endpoints. */\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 /** `1` = approved, `2` = not found / not processed. */\n codigo: '1' | '2';\n estado: 'Aprobación comercial aprobada' | 'Aprobación 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/** Default lifetime of a cached submission: 24 hours. */\nconst DEFAULT_IDEMPOTENCY_TTL_MS = 24 * 60 * 60 * 1000;\n/** Sweep expired entries once the map grows past this many live slots. */\nconst IDEMPOTENCY_SWEEP_THRESHOLD = 1_000;\n\nexport interface InMemoryIdempotencyStoreOptions {\n /** How long a cached entry stays valid. Defaults to 24 hours. */\n readonly ttlMs?: number;\n /** Clock used for expiry, injectable for tests. Defaults to `Date.now`. */\n readonly now?: () => number;\n}\n\ninterface IdempotencyEntry {\n readonly value: unknown;\n readonly expiresAt: number;\n}\n\n/**\n * Process-local default. Fine for single-instance usage and tests.\n *\n * Entries expire after `ttlMs` so a long-running process cannot grow without\n * bound; reads drop expired entries and the map is swept once it passes\n * `IDEMPOTENCY_SWEEP_THRESHOLD`. For more than one instance, back the store\n * with Redis or Postgres.\n */\nexport class InMemoryIdempotencyStore implements IdempotencyStore {\n private readonly entries = new Map<string, IdempotencyEntry>();\n private readonly ttlMs: number;\n private readonly now: () => number;\n\n constructor(options: InMemoryIdempotencyStoreOptions = {}) {\n this.ttlMs = options.ttlMs ?? DEFAULT_IDEMPOTENCY_TTL_MS;\n if (!Number.isFinite(this.ttlMs) || this.ttlMs <= 0) {\n throw new RangeError('ttlMs must be a positive finite number');\n }\n this.now = options.now ?? Date.now;\n }\n\n /** Number of live entries; expired ones are swept first. */\n get size(): number {\n this.sweepExpired();\n return this.entries.size;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const entry = this.entries.get(key);\n if (entry === undefined) {\n return undefined;\n }\n if (entry.expiresAt <= this.now()) {\n this.entries.delete(key);\n return undefined;\n }\n return entry.value as T;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.entries.set(key, { value, expiresAt: this.now() + this.ttlMs });\n if (this.entries.size > IDEMPOTENCY_SWEEP_THRESHOLD) {\n this.sweepExpired();\n }\n }\n\n async delete(key: string): Promise<void> {\n this.entries.delete(key);\n }\n\n private sweepExpired(): void {\n const now = this.now();\n for (const [key, entry] of this.entries) {\n if (entry.expiresAt <= now) {\n this.entries.delete(key);\n }\n }\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 { 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\ninterface XmldomDocument extends Document {\n childNodes: NodeListOf<ChildNode>;\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 // xml-crypto canonicalizes the referenced node-set with inclusive C14N\n // 1.0 once the transform chain is done (see `canonicalize` in\n // signed-xml.js) and hands those bytes to the digest algorithm — the\n // exact form DGII hashes. The built-in SHA-256 is therefore already\n // correct, and it also emits the standard DigestMethod URI a .NET/DGII\n // verifier expects.\n sig.addReference({\n xpath: `//*[local-name(.)='${elementName}']`,\n transforms: [ENVELOPED],\n digestAlgorithm: SHA256,\n isEmptyUri: true,\n });\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","/**\n * Tolerant element-text extraction for signed DGII XML.\n *\n * The SDK never owns the XML it inspects: DGII responses, .NET-produced\n * signatures, and third-party generators all wrap the same element in a\n * namespace prefix and add attributes to it. A literal `<tag>` match misses\n * those variants and silently degrades the caller to a fallback — which on the\n * idempotency path means a duplicate fiscal submission.\n */\n\nconst PATTERN_CACHE = new Map<string, RegExp>();\n\n/**\n * Attribute spans may contain `>` inside quotes (`nota=\"a > b\"`), so both\n * quoted forms get their own alternative instead of a blanket `[^>]*`.\n */\nconst ATTRIBUTE_SPAN = `(?:[^>\"']|\"[^\"]*\"|'[^']*')*`;\n\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst elementPattern = (tag: string): RegExp => {\n const cached = PATTERN_CACHE.get(tag);\n if (cached !== undefined) {\n return cached;\n }\n const name = escapeRegExp(tag);\n const prefix = '(?:[\\\\w.-]+:)?';\n const pattern = new RegExp(\n `<${prefix}${name}${ATTRIBUTE_SPAN}>([\\\\s\\\\S]*?)<\\\\/${prefix}${name}\\\\s*>`,\n );\n PATTERN_CACHE.set(tag, pattern);\n return pattern;\n};\n\n/**\n * Text content of the first `<tag>` element, tolerating a namespace prefix\n * (`ns:eNCF`) and attributes (`<eNCF version=\"1.0\">`).\n *\n * Returns `undefined` when the element is absent, self-closing, or blank, so\n * callers fall back deliberately instead of building a key out of an empty\n * segment. Matching is case-sensitive, as XML element names are.\n */\nexport const extractElementText = (\n xml: string,\n tag: string,\n): string | undefined => {\n const match = elementPattern(tag).exec(xml);\n const text = match?.[1]?.trim();\n return text === undefined || text === '' ? undefined : text;\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';\nimport { extractElementText } from './xml.js';\n\n/** First 6 chars of the `<SignatureValue>` (DGII security code). */\nexport const getCodeSixDigitfromSignature = (\n signedXml: string,\n): Result<string, DgiiError> => {\n const value = extractElementText(signedXml, 'SignatureValue');\n if (value === undefined) {\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 { extractElementText } from './xml.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\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 = extractElementText(signedXml, 'RNCEmisor') ?? 'unknown-rnc';\n // ACECF carries `eNCF`; ANECF uses `RangoNCF`. Fall back to the hash if\n // neither is present, so the key is still unique per document.\n const ncf =\n extractElementText(signedXml, 'eNCF') ??\n extractElementText(signedXml, 'RangoNCF') ??\n 'unknown-ncf';\n return `${rnc}:${ncf}:${sha256Hex(signedXml)}`;\n }\n\n /**\n * Run a submission through the persist-before-transmit idempotency flow.\n *\n * The pending marker is written first so an interrupted send can be\n * reconciled instead of re-issued; a successful response replaces it, and\n * a failure clears it so the caller can retry.\n */\n private async submitIdempotent<T>(\n key: string,\n send: () => Promise<Result<T, DgiiError>>,\n ): Promise<Result<T, DgiiError>> {\n const cached = await this.idempotency.get<T | PendingSubmission>(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 await this.idempotency.set(key, PENDING_SUBMISSION);\n const result = await send();\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 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 return this.submitIdempotent(key, () => {\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.SendInvoice)\n : buildUrl(this.environment, Endpoint.SendInvoice);\n return this.http.postMultipart<InvoiceResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendInvoice },\n );\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 return this.submitIdempotent(key, () =>\n this.http.postMultipart<InvoiceSummaryResponse>(\n buildUrl(this.environment, Endpoint.SendSummary, BaseUrl.CF),\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendSummary },\n ),\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 /**\n * Submit a signed commercial approval (ACECF). Idempotent like submissions,\n * keyed on `RNC + eNCF + SHA-256(signed XML)`.\n */\n sendCommercialApproval(\n signedXml: string,\n fileName: string,\n ): Promise<Result<CommercialApprovalResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n return this.submitIdempotent(key, () =>\n this.http.postMultipart<CommercialApprovalResponse>(\n buildUrl(this.environment, Endpoint.CommercialApproval),\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.CommercialApproval },\n ),\n );\n }\n\n /**\n * Submit a signed range-voiding request (ANECF). Idempotent like\n * submissions, keyed on `RNC + RangoNCF + SHA-256(signed XML)`.\n */\n voidENCF(\n signedXml: string,\n fileName: string,\n ): Promise<Result<VoidNCFResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n return this.submitIdempotent(key, () =>\n this.http.postMultipart<VoidNCFResponse>(\n buildUrl(this.environment, Endpoint.Void),\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.Void },\n ),\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/xml.ts","../src/reception.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 './reception.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 /**\n * Synchronous acknowledgement text. DGII sends this as a singular string on\n * the general reception endpoint (`recepcion/api/FacturasElectronicas`).\n */\n mensaje?: string;\n /** Tolerated array form used by the RFCE and status endpoints. */\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 /** `1` = approved, `2` = not found / not processed. */\n codigo: '1' | '2';\n estado: 'Aprobación comercial aprobada' | 'Aprobación 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/** Default lifetime of a cached submission: 24 hours. */\nconst DEFAULT_IDEMPOTENCY_TTL_MS = 24 * 60 * 60 * 1000;\n/** Sweep expired entries once the map grows past this many live slots. */\nconst IDEMPOTENCY_SWEEP_THRESHOLD = 1_000;\n\nexport interface InMemoryIdempotencyStoreOptions {\n /** How long a cached entry stays valid. Defaults to 24 hours. */\n readonly ttlMs?: number;\n /** Clock used for expiry, injectable for tests. Defaults to `Date.now`. */\n readonly now?: () => number;\n}\n\ninterface IdempotencyEntry {\n readonly value: unknown;\n readonly expiresAt: number;\n}\n\n/**\n * Process-local default. Fine for single-instance usage and tests.\n *\n * Entries expire after `ttlMs` so a long-running process cannot grow without\n * bound; reads drop expired entries and the map is swept once it passes\n * `IDEMPOTENCY_SWEEP_THRESHOLD`. For more than one instance, back the store\n * with Redis or Postgres.\n */\nexport class InMemoryIdempotencyStore implements IdempotencyStore {\n private readonly entries = new Map<string, IdempotencyEntry>();\n private readonly ttlMs: number;\n private readonly now: () => number;\n\n constructor(options: InMemoryIdempotencyStoreOptions = {}) {\n this.ttlMs = options.ttlMs ?? DEFAULT_IDEMPOTENCY_TTL_MS;\n if (!Number.isFinite(this.ttlMs) || this.ttlMs <= 0) {\n throw new RangeError('ttlMs must be a positive finite number');\n }\n this.now = options.now ?? Date.now;\n }\n\n /** Number of live entries; expired ones are swept first. */\n get size(): number {\n this.sweepExpired();\n return this.entries.size;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const entry = this.entries.get(key);\n if (entry === undefined) {\n return undefined;\n }\n if (entry.expiresAt <= this.now()) {\n this.entries.delete(key);\n return undefined;\n }\n return entry.value as T;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.entries.set(key, { value, expiresAt: this.now() + this.ttlMs });\n if (this.entries.size > IDEMPOTENCY_SWEEP_THRESHOLD) {\n this.sweepExpired();\n }\n }\n\n async delete(key: string): Promise<void> {\n this.entries.delete(key);\n }\n\n private sweepExpired(): void {\n const now = this.now();\n for (const [key, entry] of this.entries) {\n if (entry.expiresAt <= now) {\n this.entries.delete(key);\n }\n }\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 /** Runs before every authenticated request; may refresh credentials. */\n beforeRequest?: () => Promise<void>;\n /** Runs on a 401; return `true` to replay the request once. */\n onUnauthorized?: () => Promise<boolean>;\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 /** Skip the auth hooks (used by the authentication round-trip itself). */\n skipAuthHooks?: boolean;\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 private readonly beforeRequest: (() => Promise<void>) | undefined;\n private readonly onUnauthorized: (() => Promise<boolean>) | undefined;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.token = options.token;\n this.beforeRequest = options.beforeRequest;\n this.onUnauthorized = options.onUnauthorized;\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 getToken(): string | undefined {\n return this.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 if (!options.skipAuthHooks) {\n await this.beforeRequest?.();\n }\n\n const first = await this.execute<T>(options);\n\n if (\n !options.skipAuthHooks &&\n first.isErr() &&\n first.error.status === 401 &&\n this.onUnauthorized !== undefined\n ) {\n const replayed = await this.onUnauthorized();\n if (replayed) {\n return this.execute<T>(options);\n }\n }\n return first;\n }\n\n private async execute<T>(\n options: RequestOptions,\n ): 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?: {\n absoluteUrl?: boolean;\n resource?: string;\n skipAuthHooks?: boolean;\n },\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 skipAuthHooks: opts?.skipAuthHooks,\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?: {\n absoluteUrl?: boolean;\n resource?: string;\n skipAuthHooks?: boolean;\n },\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 skipAuthHooks: opts?.skipAuthHooks,\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 { 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\ninterface XmldomDocument extends Document {\n childNodes: NodeListOf<ChildNode>;\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 // xml-crypto canonicalizes the referenced node-set with inclusive C14N\n // 1.0 once the transform chain is done (see `canonicalize` in\n // signed-xml.js) and hands those bytes to the digest algorithm — the\n // exact form DGII hashes. The built-in SHA-256 is therefore already\n // correct, and it also emits the standard DigestMethod URI a .NET/DGII\n // verifier expects.\n sig.addReference({\n xpath: `//*[local-name(.)='${elementName}']`,\n transforms: [ENVELOPED],\n digestAlgorithm: SHA256,\n isEmptyUri: true,\n });\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","/**\n * Tolerant element-text extraction for signed DGII XML.\n *\n * The SDK never owns the XML it inspects: DGII responses, .NET-produced\n * signatures, and third-party generators all wrap the same element in a\n * namespace prefix and add attributes to it. A literal `<tag>` match misses\n * those variants and silently degrades the caller to a fallback — which on the\n * idempotency path means a duplicate fiscal submission.\n */\n\nconst PATTERN_CACHE = new Map<string, RegExp>();\n\n/**\n * Attribute spans may contain `>` inside quotes (`nota=\"a > b\"`), so both\n * quoted forms get their own alternative instead of a blanket `[^>]*`.\n */\nconst ATTRIBUTE_SPAN = `(?:[^>\"']|\"[^\"]*\"|'[^']*')*`;\n\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst elementPattern = (tag: string): RegExp => {\n const cached = PATTERN_CACHE.get(tag);\n if (cached !== undefined) {\n return cached;\n }\n const name = escapeRegExp(tag);\n const prefix = '(?:[\\\\w.-]+:)?';\n const pattern = new RegExp(\n `<${prefix}${name}${ATTRIBUTE_SPAN}>([\\\\s\\\\S]*?)<\\\\/${prefix}${name}\\\\s*>`,\n );\n PATTERN_CACHE.set(tag, pattern);\n return pattern;\n};\n\n/**\n * Text content of the first `<tag>` element, tolerating a namespace prefix\n * (`ns:eNCF`) and attributes (`<eNCF version=\"1.0\">`).\n *\n * Returns `undefined` when the element is absent, self-closing, or blank, so\n * callers fall back deliberately instead of building a key out of an empty\n * segment. Matching is case-sensitive, as XML element names are.\n */\nexport const extractElementText = (\n xml: string,\n tag: string,\n): string | undefined => {\n const match = elementPattern(tag).exec(xml);\n const text = match?.[1]?.trim();\n return text === undefined || text === '' ? undefined : text;\n};\n\nconst ROOT_PATTERN = /<\\s*(?:[A-Za-z_][\\w.-]*:)?([A-Za-z_][\\w.-]*)[\\s/>]/;\n\n/**\n * Local name of the document's root element, ignoring the XML declaration and\n * any leading comments. Returns `undefined` when no element is present.\n *\n * DGII routing depends on the root: `<ECF>` goes to the general reception and\n * `<RFCE>` to the consumption-summary reception.\n */\nexport const extractRootElementName = (xml: string): string | undefined => {\n const stripped = xml\n .replace(/<\\?[\\s\\S]*?\\?>/g, '')\n .replace(/<!--[\\s\\S]*?-->/g, '')\n .trimStart();\n return ROOT_PATTERN.exec(stripped)?.[1];\n};\n","import { Endpoint } from './environment.js';\nimport { DgiiError } from './errors.js';\nimport { err, ok, type Result } from './result.js';\nimport { extractElementText, extractRootElementName } from './xml.js';\n\n/** Every e-CF type code defined by DGII. */\nexport const ECF_TYPE_CODES = [\n '31',\n '32',\n '33',\n '34',\n '41',\n '43',\n '44',\n '45',\n '46',\n '47',\n] as const;\n\nexport type EcfTypeCode = (typeof ECF_TYPE_CODES)[number];\n\n/**\n * Consumption invoices (E32) at or above this amount go to the general\n * reception endpoint; below it they must be sent as an RFCE summary.\n */\nexport const CONSUMPTION_SUMMARY_THRESHOLD = '250000';\n\n/** The consumption-invoice type code. */\nconst CONSUMPTION_TYPE: EcfTypeCode = '32';\n\nexport interface GeneralReceptionRoute {\n readonly kind: 'general';\n readonly endpoint: Endpoint.SendInvoice;\n}\n\nexport interface SummaryReceptionRoute {\n readonly kind: 'summary';\n readonly endpoint: Endpoint.SendSummary;\n}\n\nexport type ReceptionRoute = GeneralReceptionRoute | SummaryReceptionRoute;\n\nconst GENERAL: GeneralReceptionRoute = {\n kind: 'general',\n endpoint: Endpoint.SendInvoice,\n};\n\nconst SUMMARY: SummaryReceptionRoute = {\n kind: 'summary',\n endpoint: Endpoint.SendSummary,\n};\n\nexport const isEcfTypeCode = (value: string): value is EcfTypeCode =>\n (ECF_TYPE_CODES as readonly string[]).includes(value);\n\nconst DECIMAL_PATTERN = /^\\d+(?:\\.\\d+)?$/;\n\n/**\n * Compare two non-negative decimal strings without going through `number`, so\n * a money amount never picks up binary floating-point error.\n *\n * Returns a negative number when `a < b`, zero when equal, positive otherwise.\n */\nexport const compareDecimal = (a: string, b: string): number => {\n const [aInt = '', aFrac = ''] = a.split('.');\n const [bInt = '', bFrac = ''] = b.split('.');\n const aWhole = aInt.replace(/^0+(?=\\d)/, '');\n const bWhole = bInt.replace(/^0+(?=\\d)/, '');\n\n if (aWhole.length !== bWhole.length) {\n return aWhole.length - bWhole.length;\n }\n if (aWhole !== bWhole) {\n return aWhole < bWhole ? -1 : 1;\n }\n\n const width = Math.max(aFrac.length, bFrac.length);\n const aPadded = aFrac.padEnd(width, '0');\n const bPadded = bFrac.padEnd(width, '0');\n if (aPadded === bPadded) {\n return 0;\n }\n return aPadded < bPadded ? -1 : 1;\n};\n\nconst validationError = (message: string): DgiiError =>\n new DgiiError(message, { code: 'VALIDATION' });\n\n/**\n * Decide which DGII reception endpoint a signed document belongs to.\n *\n * - `<RFCE>` → the consumption-summary reception (`recepcionfc`).\n * - `<ECF>` with any type other than E32 → the general reception.\n * - `<ECF>` type E32 at or above RD$250,000 → the general reception.\n * - `<ECF>` type E32 below RD$250,000 → rejected: DGII only accepts the\n * summary form for those, so the caller must run `convertECF32ToRFCE` first.\n *\n * The decision reads `TipoeCF` and `MontoTotal` from the signed document, so it\n * cannot drift from what is actually being transmitted.\n */\nexport const resolveReceptionRoute = (\n signedXml: string,\n): Result<ReceptionRoute, DgiiError> => {\n const root = extractRootElementName(signedXml);\n if (root === 'RFCE') {\n return ok(SUMMARY);\n }\n if (root !== 'ECF') {\n return err(\n validationError(\n `Unsupported document root \"${root ?? 'unknown'}\"; expected \"ECF\" or \"RFCE\"`,\n ),\n );\n }\n\n const tipo = extractElementText(signedXml, 'TipoeCF');\n if (tipo === undefined) {\n return err(validationError('TipoeCF is missing from the document'));\n }\n if (!isEcfTypeCode(tipo)) {\n return err(validationError(`Unknown TipoeCF \"${tipo}\"`));\n }\n if (tipo !== CONSUMPTION_TYPE) {\n return ok(GENERAL);\n }\n\n const total = extractElementText(signedXml, 'MontoTotal');\n if (total === undefined) {\n return err(\n validationError(\n 'MontoTotal is required to route an E32 consumption invoice',\n ),\n );\n }\n if (!DECIMAL_PATTERN.test(total)) {\n return err(\n validationError(`MontoTotal \"${total}\" is not a decimal amount`),\n );\n }\n\n return compareDecimal(total, CONSUMPTION_SUMMARY_THRESHOLD) < 0\n ? err(\n validationError(\n 'An E32 below RD$250,000 must be sent as an RFCE summary; convert it with convertECF32ToRFCE first',\n ),\n )\n : ok(GENERAL);\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';\nimport { extractElementText } from './xml.js';\n\n/** First 6 chars of the `<SignatureValue>` (DGII security code). */\nexport const getCodeSixDigitfromSignature = (\n signedXml: string,\n): Result<string, DgiiError> => {\n const value = extractElementText(signedXml, 'SignatureValue');\n if (value === undefined) {\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 { resolveReceptionRoute } from './reception.js';\nimport { Signature } from './signing.js';\nimport { extractElementText } from './xml.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 * Refresh the token when its remaining lifetime falls below this window.\n * Defaults to 5 minutes.\n */\n tokenRefreshSkewMs?: number;\n /** Injectable clock (epoch milliseconds); useful for tests. */\n now?: () => number;\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\n/** Parse DGII's ISO-8601 `expira` into epoch milliseconds. */\nconst parseExpiry = (value: string | undefined): number | undefined => {\n if (value === undefined) {\n return undefined;\n }\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? undefined : parsed;\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 private readonly tokenRefreshSkewMs: number;\n private readonly now: () => number;\n private tokenExpiresAt: number | undefined;\n private refreshPromise: Promise<Result<AuthToken, DgiiError>> | undefined;\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.tokenRefreshSkewMs = options.tokenRefreshSkewMs ?? 5 * 60 * 1000;\n this.now = options.now ?? Date.now;\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 beforeRequest: async () => {\n await this.ensureToken();\n },\n onUnauthorized: () => this.reauthenticate(),\n });\n }\n\n private buildIdempotencyKey(signedXml: string): string {\n const rnc = extractElementText(signedXml, 'RNCEmisor') ?? 'unknown-rnc';\n // ACECF carries `eNCF`; ANECF uses `RangoNCF`. Fall back to the hash if\n // neither is present, so the key is still unique per document.\n const ncf =\n extractElementText(signedXml, 'eNCF') ??\n extractElementText(signedXml, 'RangoNCF') ??\n 'unknown-ncf';\n return `${rnc}:${ncf}:${sha256Hex(signedXml)}`;\n }\n\n /**\n * Run a submission through the persist-before-transmit idempotency flow.\n *\n * The pending marker is written first so an interrupted send can be\n * reconciled instead of re-issued; a successful response replaces it, and\n * a failure clears it so the caller can retry.\n */\n private async submitIdempotent<T>(\n key: string,\n send: () => Promise<Result<T, DgiiError>>,\n ): Promise<Result<T, DgiiError>> {\n const cached = await this.idempotency.get<T | PendingSubmission>(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 await this.idempotency.set(key, PENDING_SUBMISSION);\n const result = await send();\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 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 /**\n * Refresh the token when it is missing or about to expire.\n *\n * A pre-supplied `token` has no known expiry, so it is never refreshed\n * proactively — only a 401 triggers a re-authentication for it.\n */\n private async ensureToken(): Promise<Result<void, DgiiError>> {\n if (this.tokenExpiresAt === undefined) {\n return ok(undefined);\n }\n if (this.now() < this.tokenExpiresAt - this.tokenRefreshSkewMs) {\n return ok(undefined);\n }\n const refreshed = await this.refreshToken();\n return refreshed.isOk() ? ok(undefined) : err(refreshed.error);\n }\n\n /** Authenticate, coalescing concurrent refreshes into a single round-trip. */\n private refreshToken(): Promise<Result<AuthToken, DgiiError>> {\n if (this.refreshPromise !== undefined) {\n return this.refreshPromise;\n }\n const promise = this.authenticate().finally(() => {\n this.refreshPromise = undefined;\n });\n this.refreshPromise = promise;\n return promise;\n }\n\n /** Drop the rejected token and authenticate once. Returns `true` on success. */\n private async reauthenticate(): Promise<boolean> {\n this.http.clearToken();\n this.tokenExpiresAt = undefined;\n const refreshed = await this.refreshToken();\n return refreshed.isOk();\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 this.tokenExpiresAt = parseExpiry(token.value.expira);\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 skipAuthHooks: true,\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 skipAuthHooks: true,\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 skipAuthHooks: true,\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 return this.submitIdempotent(key, () => {\n const url = buyerHost\n ? buildSenderReceiverUrl(buyerHost, SenderReceiverEndpoint.SendInvoice)\n : buildUrl(this.environment, Endpoint.SendInvoice);\n return this.http.postMultipart<InvoiceResponse>(\n url,\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendInvoice },\n );\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 return this.submitIdempotent(key, () =>\n this.http.postMultipart<InvoiceSummaryResponse>(\n buildUrl(this.environment, Endpoint.SendSummary, BaseUrl.CF),\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.SendSummary },\n ),\n );\n }\n\n /**\n * Submit a signed document to the endpoint its own content belongs to.\n *\n * Reads the root element, `TipoeCF` and `MontoTotal` from the signed XML and\n * dispatches to {@link sendSummary} for an RFCE or to\n * {@link sendElectronicDocument} for an ECF. An E32 below RD$250,000 is\n * rejected because DGII only accepts the summary form for those.\n */\n async sendDocument(\n signedXml: string,\n fileName: string,\n buyerHost?: string,\n ): Promise<Result<InvoiceResponse | InvoiceSummaryResponse, DgiiError>> {\n const route = resolveReceptionRoute(signedXml);\n if (route.isErr()) {\n return err(route.error);\n }\n if (route.value.kind === 'summary') {\n if (buyerHost !== undefined) {\n return err(\n new DgiiError(\n 'An RFCE summary cannot be delivered directly to a buyer host',\n { code: 'VALIDATION' },\n ),\n );\n }\n return this.sendSummary(signedXml, fileName);\n }\n return this.sendElectronicDocument(signedXml, fileName, buyerHost);\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 /**\n * Submit a signed commercial approval (ACECF). Idempotent like submissions,\n * keyed on `RNC + eNCF + SHA-256(signed XML)`.\n */\n sendCommercialApproval(\n signedXml: string,\n fileName: string,\n ): Promise<Result<CommercialApprovalResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n return this.submitIdempotent(key, () =>\n this.http.postMultipart<CommercialApprovalResponse>(\n buildUrl(this.environment, Endpoint.CommercialApproval),\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.CommercialApproval },\n ),\n );\n }\n\n /**\n * Submit a signed range-voiding request (ANECF). Idempotent like\n * submissions, keyed on `RNC + RangoNCF + SHA-256(signed XML)`.\n */\n voidENCF(\n signedXml: string,\n fileName: string,\n ): Promise<Result<VoidNCFResponse, DgiiError>> {\n const key = this.buildIdempotencyKey(signedXml);\n return this.submitIdempotent(key, () =>\n this.http.postMultipart<VoidNCFResponse>(\n buildUrl(this.environment, Endpoint.Void),\n fileName,\n signedXml,\n { absoluteUrl: true, resource: Endpoint.Void },\n ),\n );\n }\n}\n"],"mappings":"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","names":["Environment","Endpoint","SenderReceiverEndpoint","TrackStatusEnum","err","forge","crypto","convert","import_node_crypto","url"]}