UNPKG

osodreamer-sri-xml-signer

Version:

Genera, firma, valida y autoriza comprobantes electrónicos XML para el SRI de Ecuador con certificados digitales (.p12) y estándar XAdES-BES.

2,468 lines 98.7 kB
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __decoratorStart = (base) => {
  var _a;
  return [, , , __create((_a = base == null ? void 0 : base[__knownSymbol("metadata")]) != null ? _a : null)];
};
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
var __runInitializers = (array, flags, self, value) => {
  for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
  return value;
};
var __decorateElement = (array, flags, name, decorators, target, extra) => {
  var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
  var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
  var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
  var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
    return __privateGet(this, extra);
  }, set [name](x) {
    return __privateSet(this, extra, x);
  } }, name));
  k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
  for (var i = decorators.length - 1; i >= 0; i--) {
    ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
    if (k) {
      ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
      if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
      if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
    }
    it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
    if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
    else if (typeof it !== "object" || it === null) __typeError("Object expected");
    else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
  }
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);

// src/sign-xml/common/utils/crypto.util.ts
import * as forge from "node-forge";
var CryptoUtils = class {
  hexToBase64(str) {
    let hex = ("00" + str).slice(0 - str.length - str.length % 2);
    const binary = hex.replace(/\r|\n/g, "").replace(
      /([\da-fA-F]{2}) ?/g,
      (match) => String.fromCharCode(parseInt(match, 16))
    );
    return forge.util.encode64(binary);
  }
  bigint3base64(bigint) {
    const hex = bigint.toString(16).padStart(2, "0");
    const binary = hex.match(/\w{2}/g).map((a) => String.fromCharCode(parseInt(a, 16))).join("");
    const base64 = forge.util.encode64(binary);
    return base64.match(/.{1,76}/g).join("\n");
  }
  p_obtener_aleatorio() {
    const arr = new Uint32Array(1);
    crypto.getRandomValues(arr);
    return 1e5 + arr[0] % 99e5;
  }
};

// src/sign-xml/infrastructure/errors/infrastructure.error.ts
var InfrastructureError = class extends Error {
  constructor(message) {
    super(message);
    this.name = "InfrastructureError";
  }
};
var UnknownSignStrategyError = class extends InfrastructureError {
  constructor(friendlyName) {
    super(`No existe estrategia para el certificado: ${friendlyName}`);
    this.name = "UnknownSignStrategyError";
  }
};
var SignStrategyError = class extends InfrastructureError {
  constructor(message) {
    super(message);
    this.name = "SignStrategyError";
  }
};
var SigningKeyNotFoundError = class extends SignStrategyError {
  constructor(friendlyName) {
    super(
      `No se encontr\xF3 la clave de firma para el certificado: ${friendlyName}`
    );
    this.name = "SigningKeyNotFoundError";
  }
};
var PrivateKeyExtractionError = class extends SignStrategyError {
  constructor(sourceLabel = "archivo P12") {
    super(`No se pudo extraer la clave privada desde ${sourceLabel}.`);
    this.name = "PrivateKeyExtractionError";
  }
};
var UanatacaCertificateNotFoundError = class extends SignStrategyError {
  constructor() {
    super("No se encontr\xF3 el certificado para UANATACA.");
    this.name = "UanatacaCertificateNotFoundError";
  }
};
var InvalidP12StructureError = class extends Error {
  constructor() {
    super("El archivo no es un archivo PKCS#12 (P12) v\xE1lido.");
    this.name = "InvalidP12StructureError";
    Object.setPrototypeOf(this, new.target.prototype);
  }
};
var InvalidP12PasswordError = class extends Error {
  constructor() {
    super("El archivo P12 es v\xE1lido, pero la contrase\xF1a es incorrecta.");
    this.name = "InvalidP12PasswordError";
    Object.setPrototypeOf(this, new.target.prototype);
  }
};
var InvalidXmlStructureError = class extends Error {
  constructor(message = "El archivo proporcionado no es un XML v\xE1lido.") {
    super(message);
    this.name = "InvalidXmlStructureError";
    Object.setPrototypeOf(this, new.target.prototype);
  }
};

// src/sign-xml/infrastructure/certificate/strategies/banco-central.strategy.ts
import * as forge2 from "node-forge";
var BancoCentralStrategy = class {
  supports(friendlyName) {
    return /BANCO CENTRAL/i.test(friendlyName);
  }
  getPrivateKey(bags) {
    const item = bags.find(
      (bag) => {
        var _a, _b;
        return /Signing Key/i.test((_b = (_a = bag.attributes) == null ? void 0 : _a.friendlyName) == null ? void 0 : _b[0]);
      }
    );
    if (!item) throw new SigningKeyNotFoundError("BANCO CENTRAL");
    if (item == null ? void 0 : item.key) {
      return item.key;
    } else if (item == null ? void 0 : item.asn1) {
      return forge2.pki.privateKeyFromAsn1(item.asn1);
    } else {
      throw new PrivateKeyExtractionError();
    }
  }
  overrideIssuerName(certBags) {
    const cert = certBags[forge2.pki.oids.certBag][0].cert;
    return cert.issuer.attributes.reverse().map((attr) => `${attr.shortName}=${attr.value}`).join(",");
  }
};

// src/sign-xml/infrastructure/certificate/strategies/security-data.strategy.ts
import * as forge3 from "node-forge";
var SecurityDataStrategy = class {
  supports(friendlyName) {
    return /SECURITY DATA/i.test(friendlyName);
  }
  getPrivateKey(bags) {
    const item = bags[0];
    if (!item) throw new SigningKeyNotFoundError("SECURITY DATAL");
    if (item == null ? void 0 : item.key) {
      return item.key;
    } else if (item == null ? void 0 : item.asn1) {
      return forge3.pki.privateKeyFromAsn1(item.asn1);
    } else {
      throw new PrivateKeyExtractionError();
    }
  }
  overrideIssuerName(certBags) {
    const cert = certBags[forge3.pki.oids.certBag][0].cert;
    return cert.issuer.attributes.reverse().map((attr) => `${attr.shortName}=${attr.value}`).join(",");
  }
};

// src/sign-xml/infrastructure/certificate/strategies/uanataca.strategy.ts
import * as forge4 from "node-forge";
var UanatacaStrategy = class {
  supports(friendlyName) {
    return /UANATACA/i.test(friendlyName);
  }
  getPrivateKey(bags) {
    const item = bags[0];
    if (!item) throw new SigningKeyNotFoundError("UANATACA");
    if (item == null ? void 0 : item.key) {
      return item.key;
    } else if (item == null ? void 0 : item.asn1) {
      return forge4.pki.privateKeyFromAsn1(item.asn1);
    } else {
      throw new PrivateKeyExtractionError();
    }
  }
  overrideIssuerName(certBags) {
    const certItems = certBags[forge4.pki.oids.certBag];
    if (!certItems || !certItems.length) {
      throw new UanatacaCertificateNotFoundError();
    }
    const cert = certItems[0].cert;
    return this.getX509IssuerName(cert);
  }
  getX509IssuerName(cert) {
    const issuerName = cert.issuer.attributes.reverse().filter((attr) => attr.shortName || attr.type).map((attr) => {
      if (attr.shortName) {
        return `${attr.shortName}=${attr.value}`;
      } else {
        return `${attr.type}=${this.hexEncodeUtf8(attr.value)}`;
      }
    }).join(",");
    return issuerName;
  }
  hexEncodeUtf8(value) {
    const utf8Bytes = forge4.util.encodeUtf8(value);
    const hex = forge4.util.bytesToHex(utf8Bytes);
    return `#0c${utf8Bytes.length.toString(16).padStart(2, "0")}${hex}`;
  }
};

// src/sign-xml/infrastructure/certificate/factories/sign-strategy.factory.ts
var SignStrategyFactory = class {
  constructor() {
    this.strategies = [
      new BancoCentralStrategy(),
      new SecurityDataStrategy(),
      new UanatacaStrategy()
    ];
  }
  getStrategy(friendlyName) {
    const strategy = this.strategies.find((s) => s.supports(friendlyName));
    if (!strategy) {
      throw new UnknownSignStrategyError(friendlyName);
    }
    return strategy;
  }
};

// src/sign-xml/infrastructure/certificate/certificate-provider.implement.ts
import * as forge5 from "node-forge";
var CertificateProviderImplement = class {
  constructor(p12Buffer, password, strategyFactory, crypto2) {
    this.p12Buffer = p12Buffer;
    this.password = password;
    this.strategyFactory = strategyFactory;
    this.crypto = crypto2;
  }
  async getCertificateData() {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i;
    const uint8Array = new Uint8Array(this.p12Buffer);
    const p12Base64 = forge5.util.binary.base64.encode(uint8Array);
    const p12Decoded = forge5.util.decode64(p12Base64);
    const p12Asn1 = forge5.asn1.fromDer(p12Decoded);
    const p12 = forge5.pkcs12.pkcs12FromAsn1(p12Asn1, this.password);
    const keyBags = p12.getBags({
      bagType: forge5.pki.oids.pkcs8ShroudedKeyBag
    });
    const certBags = p12.getBags({ bagType: forge5.pki.oids.certBag });
    const certificates = certBags[forge5.oids.certBag];
    const friendlyName = (_i = (_c = (_b = (_a = certificates == null ? void 0 : certificates[1]) == null ? void 0 : _a.attributes) == null ? void 0 : _b.friendlyName) == null ? void 0 : _c[0]) != null ? _i : (_h = (_g = (_f = (_e = (_d = certificates == null ? void 0 : certificates[0]) == null ? void 0 : _d.cert) == null ? void 0 : _e.issuer) == null ? void 0 : _f.attributes) == null ? void 0 : _g[2]) == null ? void 0 : _h.value;
    const strategy = this.strategyFactory.getStrategy(friendlyName);
    const privateKey = strategy.getPrivateKey(
      keyBags[forge5.oids.pkcs8ShroudedKeyBag]
    );
    const issuerName = strategy.overrideIssuerName(certBags);
    const mainCertificate = certificates.reduce((prev, current) => {
      return current.cert.extensions.length > prev.cert.extensions.length ? current : prev;
    });
    const certificate = mainCertificate.cert;
    const certificateX509_asn1 = forge5.pki.certificateToAsn1(certificate);
    const certificateX509_der = forge5.asn1.toDer(certificateX509_asn1);
    const certificateX509_der_hash = forge5.util.encode64(
      forge5.sha1.create().update(certificateX509_der.bytes()).digest().bytes()
    );
    const X509SerialNumber = new forge5.jsbn.BigInteger(
      Array.from(Buffer.from(certificate.serialNumber, "hex"))
    ).toString();
    const certificateX509 = forge5.util.encode64(certificateX509_der.bytes());
    const exponent = this.crypto.hexToBase64(privateKey.e.data[0].toString(16));
    const modulus = this.crypto.bigint3base64(privateKey.n);
    return {
      certificate,
      certificateX509,
      privateKey,
      issuerName,
      serialNumber: X509SerialNumber,
      base64Der: certificateX509_der_hash,
      publicKey: {
        modulus,
        exponent
      }
    };
  }
};

// src/sign-xml/application/use-cases.ts
var SignXmlUseCase = class {
  constructor(signerService, injector) {
    this.signerService = signerService;
    this.injector = injector;
  }
  async execute(input) {
    const { xmlToSign, certData } = input;
    const signatureXml = await this.signerService.sign({
      xmlToSign,
      certData
    });
    const finalXml = this.injector.insertSignature(signatureXml.xadesBes);
    return finalXml;
  }
};

// src/sign-xml/domain/enums/xml-namespaces.enum.ts
var XMLNS_ATTRIBUTE = `xmlns:ds="${"http://www.w3.org/2000/09/xmldsig#" /* DS */}" xmlns:etsi="${"http://uri.etsi.org/01903/v1.3.2#" /* ETSI */}"`;

// src/sign-xml/domain/builders/keyInfo.builder.ts
var KeyInfoBuilder = class {
  build(params) {
    const { certificateNumber, certificateX509, modulus, exponent } = params;
    return [
      `<ds:KeyInfo ${XMLNS_ATTRIBUTE} Id="Certificate${certificateNumber}">`,
      "\n<ds:X509Data>",
      "\n<ds:X509Certificate>\n",
      certificateX509,
      "\n</ds:X509Certificate>",
      "\n</ds:X509Data>",
      "\n<ds:KeyValue>",
      "\n<ds:RSAKeyValue>",
      "\n<ds:Modulus>\n",
      modulus,
      "\n</ds:Modulus>",
      "\n<ds:Exponent>",
      exponent,
      "</ds:Exponent>",
      "\n</ds:RSAKeyValue>",
      "\n</ds:KeyValue>",
      "\n</ds:KeyInfo>"
    ].join("");
  }
};

// src/sign-xml/domain/builders/signed-info.builder.ts
var SignedInfoBuilder = class {
  build(params) {
    const { ids, sha1_SignedProperties, sha1_certificado, sha1_comprobante } = params;
    return [
      `<ds:SignedInfo ${XMLNS_ATTRIBUTE} Id="Signature-SignedInfo${ids.signedInfoNumber}">`,
      `
<ds:CanonicalizationMethod Algorithm="${"http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /* XML_C14N_20010315 */}">`,
      "</ds:CanonicalizationMethod>",
      `
<ds:SignatureMethod Algorithm="${"http://www.w3.org/2000/09/xmldsig#rsa-sha1" /* RSA_SHA1 */}">`,
      "</ds:SignatureMethod>",
      `
<ds:Reference Id="SignedPropertiesID${ids.signedPropertiesIdNumber}" Type="${"http://uri.etsi.org/01903#SignedProperties" /* SIGNED_PROPERTIES */}" URI="#Signature${ids.signatureNumber}-SignedProperties${ids.signedPropertiesNumber}">`,
      `
<ds:DigestMethod Algorithm="${"http://www.w3.org/2000/09/xmldsig#sha1" /* SHA1 */}">`,
      "</ds:DigestMethod>",
      "\n<ds:DigestValue>",
      sha1_SignedProperties,
      "</ds:DigestValue>",
      "\n</ds:Reference>",
      `
<ds:Reference URI="#Certificate${ids.certificateNumber}">`,
      `
<ds:DigestMethod Algorithm="${"http://www.w3.org/2000/09/xmldsig#sha1" /* SHA1 */}">`,
      "</ds:DigestMethod>",
      "\n<ds:DigestValue>",
      sha1_certificado,
      "</ds:DigestValue>",
      "\n</ds:Reference>",
      `
<ds:Reference Id="Reference-ID-${ids.referenceIdNumber}" URI="#comprobante">`,
      "\n<ds:Transforms>",
      `
<ds:Transform Algorithm="${"http://www.w3.org/2000/09/xmldsig#enveloped-signature" /* ENVELOPED_SIGNATURE */}">`,
      "</ds:Transform>",
      "\n</ds:Transforms>",
      `
<ds:DigestMethod Algorithm="${"http://www.w3.org/2000/09/xmldsig#sha1" /* SHA1 */}">`,
      "</ds:DigestMethod>",
      "\n<ds:DigestValue>",
      sha1_comprobante,
      "</ds:DigestValue>",
      "\n</ds:Reference>",
      "\n</ds:SignedInfo>"
    ].join("");
  }
};

// src/sign-xml/domain/builders/signed-properties.builder.ts
var SignedPropertiesBuilder = class {
  constructor(clock) {
    this.clock = clock;
  }
  build(params) {
    const {
      signatureNumber,
      signedPropertiesNumber,
      certificateX509_der_hash,
      issuerName,
      X509SerialNumber,
      referenceIdNumber
    } = params;
    const timestamp = this.clock.nowISO();
    return [
      `<etsi:SignedProperties ${XMLNS_ATTRIBUTE} Id="Signature${signatureNumber}-SignedProperties${signedPropertiesNumber}">`,
      "<etsi:SignedSignatureProperties>",
      "<etsi:SigningTime>",
      timestamp,
      "</etsi:SigningTime>",
      "<etsi:SigningCertificate>",
      "<etsi:Cert>",
      "<etsi:CertDigest>",
      `<ds:DigestMethod Algorithm="${"http://www.w3.org/2000/09/xmldsig#sha1" /* SHA1 */}">`,
      "</ds:DigestMethod>",
      "<ds:DigestValue>",
      certificateX509_der_hash,
      "</ds:DigestValue>",
      "</etsi:CertDigest>",
      "<etsi:IssuerSerial>",
      "<ds:X509IssuerName>",
      issuerName,
      "</ds:X509IssuerName>",
      "<ds:X509SerialNumber>",
      X509SerialNumber,
      "</ds:X509SerialNumber>",
      "</etsi:IssuerSerial>",
      "</etsi:Cert>",
      "</etsi:SigningCertificate>",
      "</etsi:SignedSignatureProperties>",
      "<etsi:SignedDataObjectProperties>",
      `<etsi:DataObjectFormat ObjectReference="#Reference-ID-${referenceIdNumber}">`,
      "<etsi:Description>contenido comprobante</etsi:Description>",
      "<etsi:MimeType>text/xml</etsi:MimeType>",
      "</etsi:DataObjectFormat>",
      "</etsi:SignedDataObjectProperties>",
      "</etsi:SignedProperties>"
    ].join("");
  }
};

// src/sign-xml/domain/assemblers/xades-document.assembler.ts
var XadesDocumentAssembler = class {
  build(params) {
    const { KeyInfo, SignedInfo, SignedProperties, ids, signature } = params;
    return [
      `<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#" Id="Signature${ids.signatureNumber}">`,
      "\n" + SignedInfo,
      `
<ds:SignatureValue Id="SignatureValue${ids.signatureValueNumber}">
`,
      signature,
      "\n</ds:SignatureValue>",
      "\n" + KeyInfo,
      `
<ds:Object Id="Signature${ids.signatureNumber}-Object${ids.ObjectNumber}">`,
      `<etsi:QualifyingProperties Target="#Signature${ids.signatureNumber}">`,
      SignedProperties,
      "</etsi:QualifyingProperties>",
      "</ds:Object>",
      "</ds:Signature>"
    ].join("");
  }
};

// src/utils/date-utils.ts
function formatDDMMYYYY(date) {
  const d = String(date.getDate()).padStart(2, "0");
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const y = date.getFullYear();
  return `${d}${m}${y}`;
}
function formatDDMM(date) {
  const d = String(date.getDate()).padStart(2, "0");
  const m = String(date.getMonth() + 1).padStart(2, "0");
  return `${d}${m}`;
}

// src/utils/utf8.util.ts
function utf8Encode(str) {
  if (str == null) throw new TypeError("Invalid input");
  const encoder = new TextEncoder();
  const bytes = encoder.encode(str);
  return String.fromCharCode(...bytes);
}

// src/utils/xml.util.ts
function uint8ArrayToBase64(bytes) {
  let binary = "";
  const len = bytes.byteLength;
  for (let i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary);
}

// src/sign-xml/domain/xades-signature.service.ts
var XadesSignatureService = class {
  constructor(clock, canonicalizer, hasher, idGenerator, signer) {
    this.clock = clock;
    this.canonicalizer = canonicalizer;
    this.hasher = hasher;
    this.idGenerator = idGenerator;
    this.signer = signer;
  }
  async sign(data) {
    const ids = this.idGenerator.generateAll();
    const { certData, xmlToSign } = data;
    const { issuerName } = certData;
    const canonicalizedXml = await this.canonicalizer.canonicalize(xmlToSign);
    const digestXml = this.hasher.sha1Base64(utf8Encode(canonicalizedXml));
    const certDigest = certData.base64Der;
    const serialNumber = certData.serialNumber;
    const certificateX509 = certData.certificateX509;
    const modulus = certData.publicKey.modulus;
    const exponent = certData.publicKey.exponent;
    const signedPropsBuilder = new SignedPropertiesBuilder(this.clock);
    const SignedProperties = signedPropsBuilder.build({
      signatureNumber: ids.signatureNumber,
      signedPropertiesNumber: ids.signedPropertiesNumber,
      certificateX509_der_hash: certDigest,
      issuerName,
      X509SerialNumber: serialNumber,
      referenceIdNumber: ids.referenceIdNumber
    });
    const sha1_SignedProperties = this.hasher.sha1Base64(
      utf8Encode(SignedProperties)
    );
    const KeyInfo = new KeyInfoBuilder().build({
      certificateNumber: ids.certificateNumber.toString(),
      certificateX509,
      modulus,
      exponent
    });
    const sha1_certificado = this.hasher.sha1Base64(KeyInfo);
    const SignedInfo = new SignedInfoBuilder().build({
      ids,
      sha1_SignedProperties,
      sha1_certificado,
      sha1_comprobante: digestXml
    });
    const signatureValue = this.signer.signSha1RsaBase64(SignedInfo);
    const xadesBes = new XadesDocumentAssembler().build({
      ids,
      SignedInfo,
      signature: signatureValue,
      KeyInfo,
      SignedProperties
    });
    return { xadesBes };
  }
};

// src/sign-xml/infrastructure/canonicalizer/exclusive-canonicalization-ts/Algorithm.ts
var Algorithm = class {
  constructor(options) {
    this.options = options;
  }
  name() {
    return null;
  }
  /**
   * Canonicaliza un nodo XML.
   * @param node Nodo XML a procesar.
   * @returns Una promesa que se resuelve con el resultado canonicalizado.
   */
  async canonicalise(node) {
    throw new Error("not implemented");
  }
};

// src/sign-xml/infrastructure/canonicalizer/exclusive-canonicalization-ts/escape.ts
var entities = {
  "&": "&amp;",
  '"': "&quot;",
  "<": "&lt;",
  ">": "&gt;",
  "	": "&#x9;",
  "\n": "&#xA;",
  "\r": "&#xD;"
};
function escapeAttributeEntities(input) {
  return input.replace(/([&<"\t\n\r])/g, (char) => entities[char]);
}
function escapeTextEntities(input) {
  return input.replace(/([&<>\r])/g, (char) => entities[char]);
}

// src/sign-xml/infrastructure/canonicalizer/exclusive-canonicalization-ts/ExclusiveCanonicalization.ts
var ELEMENT_NODE = 1;
var TEXT_NODE = 3;
var PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = 8;
var ExclusiveCanonicalisation = class extends Algorithm {
  constructor(options = {}) {
    super(options);
    this.includeComments = !!options.includeComments;
    this.inclusiveNamespaces = options.inclusiveNamespaces || [];
  }
  name() {
    return "http://www.w3.org/2001/10/xml-exc-c14n#" + (this.includeComments ? "WithComments" : "");
  }
  getIncludeComments() {
    return this.includeComments;
  }
  setIncludeComments(include) {
    this.includeComments = !!include;
  }
  getInclusiveNamespaces() {
    return [...this.inclusiveNamespaces];
  }
  setInclusiveNamespaces(namespaces) {
    this.inclusiveNamespaces = [...namespaces];
    return this;
  }
  addInclusiveNamespace(ns) {
    this.inclusiveNamespaces.push(ns);
    return this;
  }
  async canonicalise(node) {
    return this._processInner(node);
  }
  _compareAttributes(a, b) {
    if (!a.prefix && b.prefix) return -1;
    if (!b.prefix && a.prefix) return 1;
    return a.name.localeCompare(b.name);
  }
  _compareNamespaces(a, b) {
    const attr1 = a.prefix + a.namespaceURI;
    const attr2 = b.prefix + b.namespaceURI;
    return attr1.localeCompare(attr2);
  }
  _renderAttributes(node) {
    return Array.from(node.attributes || []).filter((attr) => !attr.name.startsWith("xmlns")).sort(this._compareAttributes).map((attr) => ` ${attr.name}="${escapeAttributeEntities(attr.value)}"`).join("");
  }
  _renderNamespace(node, prefixesInScope, defaultNamespace) {
    let res = "";
    let newDefaultNamespace = defaultNamespace;
    const newPrefixesInScope = [...prefixesInScope];
    const nsListToRender = [];
    const currentNamespace = node.namespaceURI || "";
    if (node.prefix) {
      const existing = newPrefixesInScope.find((e) => e.prefix === node.prefix);
      if (!existing || existing.namespaceURI !== node.namespaceURI) {
        newPrefixesInScope.filter((e) => e.prefix !== node.prefix);
        nsListToRender.push({
          prefix: node.prefix,
          namespaceURI: node.namespaceURI
        });
        newPrefixesInScope.push({
          prefix: node.prefix,
          namespaceURI: node.namespaceURI
        });
      }
    } else if (defaultNamespace !== currentNamespace) {
      newDefaultNamespace = currentNamespace;
      res += ` xmlns="${escapeAttributeEntities(newDefaultNamespace)}"`;
    }
    for (const attr of Array.from(node.attributes || [])) {
      if (attr.prefix && attr.prefix !== "xmlns") {
        const existing = newPrefixesInScope.find(
          (e) => e.prefix === attr.prefix
        );
        if (!existing || existing.namespaceURI !== attr.namespaceURI) {
          newPrefixesInScope.filter((e) => e.prefix !== attr.prefix);
          nsListToRender.push({
            prefix: attr.prefix,
            namespaceURI: attr.namespaceURI
          });
          newPrefixesInScope.push({
            prefix: attr.prefix,
            namespaceURI: attr.namespaceURI
          });
        }
      } else if (attr.prefix === "xmlns" && this.inclusiveNamespaces.includes(attr.localName)) {
        nsListToRender.push({
          prefix: attr.localName,
          namespaceURI: attr.nodeValue
        });
      }
    }
    nsListToRender.sort(this._compareNamespaces);
    for (const ns of nsListToRender) {
      res += ` xmlns:${ns.prefix}="${escapeAttributeEntities(ns.namespaceURI)}"`;
    }
    return { rendered: res, newPrefixesInScope, newDefaultNamespace };
  }
  _renderComment(node) {
    return `<!--${escapeTextEntities(node.data)}-->`;
  }
  _renderProcessingInstruction(node) {
    return `<?${node.target}${node.data ? " " + escapeTextEntities(node.data) : ""}?>`;
  }
  _processInner(node, prefixesInScope = [], defaultNamespace = "") {
    switch (node.nodeType) {
      case TEXT_NODE:
        return escapeTextEntities(node.data);
      case COMMENT_NODE:
        return this.includeComments ? this._renderComment(node) : "";
      case PROCESSING_INSTRUCTION_NODE:
        return this._renderProcessingInstruction(node);
      case ELEMENT_NODE: {
        const el = node;
        const ns = this._renderNamespace(el, prefixesInScope, defaultNamespace);
        const attrs = this._renderAttributes(el);
        const children = Array.from(el.childNodes).map(
          (child) => this._processInner(
            child,
            ns.newPrefixesInScope,
            ns.newDefaultNamespace
          )
        ).join("");
        return `<${el.tagName}${ns.rendered}${attrs}>${children}</${el.tagName}>`;
      }
      default:
        return "";
    }
  }
};

// src/sign-xml/infrastructure/canonicalizer/canonicalizer.implement.ts
var CanonicalizerImplement = class {
  constructor(context) {
    this.context = context;
  }
  async canonicalize() {
    const targetNode = this.context.getRootNode();
    const canonicalizer = new ExclusiveCanonicalisation({
      includeComments: false,
      inclusiveNamespaces: []
    });
    return await canonicalizer.canonicalise(targetNode);
  }
};

// src/sign-xml/infrastructure/clock/clock.implement.ts
var ClockImplement = class {
  nowISO() {
    const date = /* @__PURE__ */ new Date();
    const localOffset = date.getTimezoneOffset();
    const desiredOffset = 300;
    const targetDate = localOffset === desiredOffset ? date : new Date(date.getTime() + (desiredOffset - localOffset) * 6e4);
    const y = targetDate.getFullYear();
    const mo = String(targetDate.getMonth() + 1).padStart(2, "0");
    const d = String(targetDate.getDate()).padStart(2, "0");
    const h = String(targetDate.getHours()).padStart(2, "0");
    const mi = String(targetDate.getMinutes()).padStart(2, "0");
    const s = String(targetDate.getSeconds()).padStart(2, "0");
    return `${y}-${mo}-${d}T${h}:${mi}:${s}-05:00`;
  }
};

// src/sign-xml/infrastructure/forge-rsa-sha1-signer.implementation.ts
import * as forge6 from "node-forge";
var ForgeRsaSha1Signer = class {
  constructor(privateKey) {
    this.privateKey = privateKey;
  }
  signSha1RsaBase64(input) {
    var _a, _b;
    const md3 = forge6.md.sha1.create();
    md3.update(input, "utf8");
    const rawSignature = this.privateKey.sign(md3);
    const base64Signature = forge6.util.encode64(rawSignature);
    return (_b = (_a = base64Signature.match(/.{1,76}/g)) == null ? void 0 : _a.join("\n")) != null ? _b : base64Signature;
  }
};

// src/sign-xml/infrastructure/hash/hash-provider.implement.ts
import * as forge7 from "node-forge";
var HashProviderImplement = class {
  sha1Base64(input) {
    const md3 = forge7.md.sha1.create();
    md3.update(input);
    const digestHex = md3.digest().toHex();
    const digestBytes = forge7.util.hexToBytes(digestHex);
    return forge7.util.encode64(digestBytes);
  }
  sha1RawBase64(input) {
    throw new Error("Method not implemented.");
  }
};

// src/sign-xml/infrastructure/signature-generation/signature-id-generator.implement.ts
var SignatureIdGeneratorImplement = class {
  generateAll() {
    return {
      certificateNumber: this.p_obtener_aleatorio(),
      signatureNumber: this.p_obtener_aleatorio(),
      signedPropertiesNumber: this.p_obtener_aleatorio(),
      signedInfoNumber: this.p_obtener_aleatorio(),
      signedPropertiesIdNumber: this.p_obtener_aleatorio(),
      referenceIdNumber: this.p_obtener_aleatorio(),
      signatureValueNumber: this.p_obtener_aleatorio(),
      ObjectNumber: this.p_obtener_aleatorio()
    };
  }
  p_obtener_aleatorio() {
    const arr = new Uint32Array(1);
    crypto.getRandomValues(arr);
    return (1e5 + arr[0] % 99e5).toString();
  }
};

// src/sign-xml/infrastructure/XmlSignatureInjector.ts
import { DOMParser, XMLSerializer } from "@xmldom/xmldom";
var XmlSignatureInjector = class {
  constructor(context) {
    this.context = context;
  }
  insertSignature(signatureXml) {
    const parser = new DOMParser();
    const serializer = new XMLSerializer();
    const doc = this.context.getDocument();
    const signatureNode = parser.parseFromString(
      signatureXml,
      "application/xml"
    ).documentElement;
    const imported = doc.importNode(signatureNode, true);
    doc.documentElement.appendChild(imported);
    return serializer.serializeToString(doc);
  }
};

// src/sign-xml/infrastructure/composition/buildSignXmlUseCase.ts
function buildSignXmlUseCase(privateKey, context) {
  const clock = new ClockImplement();
  const canonicalizer = new CanonicalizerImplement(context);
  const hasher = new HashProviderImplement();
  const idGenerator = new SignatureIdGeneratorImplement();
  const signer = new ForgeRsaSha1Signer(privateKey);
  const injector = new XmlSignatureInjector(context);
  const xadesService = new XadesSignatureService(
    clock,
    canonicalizer,
    hasher,
    idGenerator,
    signer
  );
  return new SignXmlUseCase(xadesService, injector);
}

// src/sign-xml/infrastructure/handlers/error.handle.ts
var ErrorHandler = class {
  static handle(error) {
    if (error instanceof UanatacaCertificateNotFoundError) {
      return {
        code: "UANATACA_CERT_NOT_FOUND",
        message: error.message,
        original: error
      };
    }
    if (error instanceof SigningKeyNotFoundError) {
      return {
        code: "SIGNING_KEY_NOT_FOUND",
        message: error.message,
        original: error
      };
    }
    if (error instanceof PrivateKeyExtractionError) {
      return {
        code: "PRIVATE_KEY_EXTRACTION_ERROR",
        message: error.message,
        original: error
      };
    }
    if (error instanceof UnknownSignStrategyError) {
      return {
        code: "UNKNOWN_SIGN_STRATEGY",
        message: error.message,
        original: error
      };
    }
    if (error instanceof SignStrategyError) {
      return {
        code: "SIGN_STRATEGY_ERROR",
        message: error.message,
        original: error
      };
    }
    if (error instanceof InvalidXmlStructureError) {
      return {
        code: "XML_STRUCTURE_ERROR",
        message: error.message,
        original: error
      };
    }
    if (error instanceof InvalidP12PasswordError) {
      return {
        code: "P12_PASSWORD_ERROR",
        message: error.message,
        original: error
      };
    }
    if (error instanceof InvalidP12StructureError) {
      return {
        code: "P12_STRUCTURE_ERROR",
        message: error.message,
        original: error
      };
    }
    if (error instanceof InfrastructureError) {
      return {
        code: "INFRASTRUCTURE_ERROR",
        message: error.message,
        original: error
      };
    }
    if (error instanceof Error) {
      return {
        code: "UNHANDLED_ERROR",
        message: error.message,
        original: error
      };
    }
    return {
      code: "UNKNOWN_ERROR",
      message: "Ha ocurrido un error desconocido",
      original: new Error(String(error))
    };
  }
};

// src/sign-xml/infrastructure/validations/p12.validation.ts
import * as forge8 from "node-forge";
function assertIsValidP12OrThrow(buffer, password) {
  const binaryStr = Array.from(buffer).map((b) => String.fromCharCode(b)).join("");
  let asn13;
  try {
    asn13 = forge8.asn1.fromDer(forge8.util.createBuffer(binaryStr, "binary"));
  } catch {
    throw new InvalidP12StructureError();
  }
  try {
    forge8.pkcs12.pkcs12FromAsn1(asn13, password);
  } catch {
    throw new InvalidP12PasswordError();
  }
}

// src/sign-xml/infrastructure/xml-dom-context/xml-dom.context.ts
import { DOMParser as DOMParser2 } from "@xmldom/xmldom";
var XmlDomContext = class {
  constructor(xmlString) {
    try {
      const dom = new DOMParser2({
        errorHandler: () => {
        }
      }).parseFromString(xmlString, "text/xml");
      this.dom = dom;
    } catch (err) {
      throw new InvalidXmlStructureError();
    }
  }
  getDocument() {
    return this.dom;
  }
  getRootNode() {
    return this.dom.documentElement;
  }
};

// src/sign-xml/sign-xml.ts
async function signXml(cmd) {
  try {
    assertIsValidP12OrThrow(cmd.p12Buffer, cmd.password);
    const certProvider = new CertificateProviderImplement(
      cmd.p12Buffer,
      cmd.password,
      new SignStrategyFactory(),
      new CryptoUtils()
    );
    const certData = await certProvider.getCertificateData();
    const xmlToSign = new TextDecoder("utf-8").decode(cmd.xmlBuffer);
    const context = new XmlDomContext(xmlToSign);
    const signXmlUseCase = buildSignXmlUseCase(certData.privateKey, context);
    const finalXml = await signXmlUseCase.execute({
      xmlToSign,
      certData
    });
    return finalXml;
  } catch (error) {
    const handled = ErrorHandler.handle(error);
    console.error(`[${handled.code}] ${handled.message}`);
    throw handled.original;
  }
}

// src/generator/const/document-types.const.ts
var documentTypeCodes = {
  factura: 1,
  comprobanteRetencion: 7,
  guiaRemision: 6,
  notaCredito: 4,
  notaDebito: 5,
  liquidacionCompra: 3
};
var documentTypeName = {
  1: "factura",
  7: "comprobanteRetencion",
  6: "guiaRemision",
  4: "notaCredito",
  5: "notaDebito",
  3: "liquidacionCompra"
};

// src/generator/enums/iva-percent-code.enum.ts
var IVA_PERCENTAGE_CODE_ENUM = /* @__PURE__ */ ((IVA_PERCENTAGE_CODE_ENUM2) => {
  IVA_PERCENTAGE_CODE_ENUM2["IVA_0"] = "0";
  IVA_PERCENTAGE_CODE_ENUM2["IVA_12"] = "2";
  IVA_PERCENTAGE_CODE_ENUM2["IVA_14"] = "3";
  IVA_PERCENTAGE_CODE_ENUM2["IVA_15"] = "4";
  IVA_PERCENTAGE_CODE_ENUM2["IVA_5"] = "5";
  IVA_PERCENTAGE_CODE_ENUM2["NO_OBJETO_IVA"] = "6";
  IVA_PERCENTAGE_CODE_ENUM2["EXENTO_IVA"] = "7";
  IVA_PERCENTAGE_CODE_ENUM2["IVA_DIFERENCIADO"] = "8";
  IVA_PERCENTAGE_CODE_ENUM2["IVA_13"] = "10";
  return IVA_PERCENTAGE_CODE_ENUM2;
})(IVA_PERCENTAGE_CODE_ENUM || {});

// src/generator/const/iva-percent-label-const.ts
var IVA_PERCENTAGE_LABELS = {
  ["0" /* IVA_0 */]: "0 (0%)",
  ["2" /* IVA_12 */]: "2 (12%)",
  ["3" /* IVA_14 */]: "3 (14%)",
  ["4" /* IVA_15 */]: "4 (15%)",
  ["5" /* IVA_5 */]: "5 (5%)",
  ["6" /* NO_OBJETO_IVA */]: "6 (No objeto de IVA)",
  ["7" /* EXENTO_IVA */]: "7 (Exento de IVA)",
  ["8" /* IVA_DIFERENCIADO */]: "8 (IVA diferenciado)",
  ["10" /* IVA_13 */]: "10 (13%)"
};

// src/generator/enums/codigo-pais.enum.ts
var CodigoPais = /* @__PURE__ */ ((CodigoPais2) => {
  CodigoPais2["AMERICAN_SAMOA"] = "016";
  CodigoPais2["BOUVET_ISLAND"] = "074";
  CodigoPais2["ARGENTINA"] = "101";
  CodigoPais2["BOLIVIA"] = "102";
  CodigoPais2["BRASIL"] = "103";
  CodigoPais2["CANAD"] = "104";
  CodigoPais2["COLOMBIA"] = "105";
  CodigoPais2["COSTA_RICA"] = "106";
  CodigoPais2["CUBA"] = "107";
  CodigoPais2["CHILE"] = "108";
  CodigoPais2["ANGUILA"] = "109";
  CodigoPais2["ESTADOS_UNIDOS"] = "110";
  CodigoPais2["GUATEMALA"] = "111";
  CodigoPais2["HAIT"] = "112";
  CodigoPais2["HONDURAS"] = "113";
  CodigoPais2["JAMAICA"] = "114";
  CodigoPais2["MALVINAS_ISLAS"] = "115";
  CodigoPais2["MXICO"] = "116";
  CodigoPais2["NICARAGUA"] = "117";
  CodigoPais2["PANAM"] = "118";
  CodigoPais2["PARAGUAY"] = "119";
  CodigoPais2["PER"] = "120";
  CodigoPais2["PUERTO_RICO"] = "121";
  CodigoPais2["REPBLICA_DOMINICANA"] = "122";
  CodigoPais2["EL_SALVADOR"] = "123";
  CodigoPais2["TRINIDAD_Y_TOBAGO"] = "124";
  CodigoPais2["URUGUAY"] = "125";
  CodigoPais2["VENEZUELA"] = "126";
  CodigoPais2["CURAZAO"] = "127";
  CodigoPais2["BAHAMAS"] = "129";
  CodigoPais2["BARBADOS"] = "130";
  CodigoPais2["GRANADA"] = "131";
  CodigoPais2["GUYANA"] = "132";
  CodigoPais2["SURINAM"] = "133";
  CodigoPais2["ANTIGUA_Y_BARBUDA"] = "134";
  CodigoPais2["BELICE"] = "135";
  CodigoPais2["DOMINICA"] = "136";
  CodigoPais2["SAN_CRISTOBAL_Y_NEVIS"] = "137";
  CodigoPais2["SANTA_LUCA"] = "138";
  CodigoPais2["SAN_VICENTE_Y_LAS_GRANAD"] = "139";
  CodigoPais2["ANTILLAS_HOLANDESAS"] = "140";
  CodigoPais2["ARUBA"] = "141";
  CodigoPais2["BERMUDA"] = "142";
  CodigoPais2["GUADALUPE"] = "143";
  CodigoPais2["GUYANA_FRANCESA"] = "144";
  CodigoPais2["ISLAS_CAIMN"] = "145";
  CodigoPais2["ISLAS_VIRGENES_BRITANICAS"] = "146";
  CodigoPais2["JOHNSTON_ISLA"] = "147";
  CodigoPais2["MARTINICA"] = "148";
  CodigoPais2["MONTSERRAT_ISLA"] = "149";
  CodigoPais2["TURCAS_Y_CAICOS_ISLAS"] = "151";
  CodigoPais2["VIRGENES_ISLAS_NORTAMER"] = "152";
  CodigoPais2["ALBANIA"] = "201";
  CodigoPais2["ALEMANIA"] = "202";
  CodigoPais2["AUSTRIA"] = "203";
  CodigoPais2["BLGICA"] = "204";
  CodigoPais2["BULGARIA"] = "205";
  CodigoPais2["ALBORAN_Y_PEREJIL"] = "207";
  CodigoPais2["DINAMARCA"] = "208";
  CodigoPais2["ESPAA"] = "209";
  CodigoPais2["FRANCIA"] = "211";
  CodigoPais2["FINLANDIA"] = "212";
  CodigoPais2["REINO_UNIDO"] = "213";
  CodigoPais2["GRECIA"] = "214";
  CodigoPais2["PAISES_BAJOS_HOLANDA"] = "215";
  CodigoPais2["HUNGRA"] = "216";
  CodigoPais2["IRLANDA"] = "217";
  CodigoPais2["ISLANDIA"] = "218";
  CodigoPais2["ITALIA"] = "219";
  CodigoPais2["LUXEMBURGO"] = "220";
  CodigoPais2["MALTA"] = "221";
  CodigoPais2["NORUEGA"] = "222";
  CodigoPais2["POLONIA"] = "223";
  CodigoPais2["PORTUGAL"] = "224";
  CodigoPais2["RUMANIA"] = "225";
  CodigoPais2["SUECIA"] = "226";
  CodigoPais2["SUIZA"] = "227";
  CodigoPais2["CANARIAS_ISLAS"] = "228";
  CodigoPais2["UCRANIA"] = "229";
  CodigoPais2["RUSIA"] = "230";
  CodigoPais2["YUGOSLAVIA"] = "231";
  CodigoPais2["ANDORRA"] = "233";
  CodigoPais2["LIECHTENSTEIN"] = "234";
  CodigoPais2["MNACO"] = "235";
  CodigoPais2["SAN_MARINO"] = "237";
  CodigoPais2["VATICANO_SANTA_SEDE"] = "238";
  CodigoPais2["GIBRALTAR"] = "239";
  CodigoPais2["BELARUS"] = "241";
  CodigoPais2["BOSNIA_Y_HERZEGOVINA"] = "242";
  CodigoPais2["CROACIA"] = "243";
  CodigoPais2["ESLOVENIA"] = "244";
  CodigoPais2["ESTONIA"] = "245";
  CodigoPais2["GEORGIA"] = "246";
  CodigoPais2["GROENLANDIA"] = "247";
  CodigoPais2["LETONIA"] = "248";
  CodigoPais2["LITUANIA"] = "249";
  CodigoPais2["MOLDOVA"] = "250";
  CodigoPais2["MACEDONIA"] = "251";
  CodigoPais2["ESLOVAQUIA"] = "252";
  CodigoPais2["ISLAS_FAROE"] = "253";
  CodigoPais2["FRENCH_SOUTHERN_TERRITORIES"] = "260";
  CodigoPais2["AFGANISTAN"] = "301";
  CodigoPais2["ARABIA_SAUDITA"] = "302";
  CodigoPais2["MYANMAR_BURMA"] = "303";
  CodigoPais2["CAMBOYA"] = "304";
  CodigoPais2["COREA_NORTE"] = "306";
  CodigoPais2["TAIWAN_CHINA"] = "307";
  CodigoPais2["FILIPINAS"] = "308";
  CodigoPais2["INDIA"] = "309";
  CodigoPais2["INDONESIA"] = "310";
  CodigoPais2["IRAK"] = "311";
  CodigoPais2["IRN_REPBLICA_ISLMICA"] = "312";
  CodigoPais2["ISRAEL"] = "313";
  CodigoPais2["JAPN"] = "314";
  CodigoPais2["JORDANIA"] = "315";
  CodigoPais2["KUWAIT"] = "316";
  CodigoPais2["LAOS_REP_POP_DEMOC"] = "317";
  CodigoPais2["LIBANO"] = "318";
  CodigoPais2["MALASIA"] = "319";
  CodigoPais2["MONGOLIA_MANCHURIA"] = "321";
  CodigoPais2["PAKISTN"] = "322";
  CodigoPais2["SIRIA"] = "323";
  CodigoPais2["TAILANDIA"] = "325";
  CodigoPais2["BAHREIN"] = "327";
  CodigoPais2["BANGLADESH"] = "328";
  CodigoPais2["BUTN"] = "329";
  CodigoPais2["COREA_DEL_SUR"] = "330";
  CodigoPais2["CHINA_POPULAR"] = "331";
  CodigoPais2["CHIPRE"] = "332";
  CodigoPais2["EMIRATOS_ARABES_UNIDOS"] = "333";
  return CodigoPais2;
})(CodigoPais || {});

// src/generator/enums/codigo-retencion.enum.ts
var CODIGO_RETENCION_ENUM = /* @__PURE__ */ ((CODIGO_RETENCION_ENUM2) => {
  CODIGO_RETENCION_ENUM2[CODIGO_RETENCION_ENUM2["IVA_CIENTO_POR_CIENTO_RESOLUCION"] = 3] = "IVA_CIENTO_POR_CIENTO_RESOLUCION";
  CODIGO_RETENCION_ENUM2[CODIGO_RETENCION_ENUM2["IVA_DOCE_POR_CIENTO_PRESUNTIVO_EDITORES"] = 4] = "IVA_DOCE_POR_CIENTO_PRESUNTIVO_EDITORES";
  CODIGO_RETENCION_ENUM2[CODIGO_RETENCION_ENUM2["IVA_CIENTO_POR_CIENTO_DISTRIBUIDORES"] = 5] = "IVA_CIENTO_POR_CIENTO_DISTRIBUIDORES";
  CODIGO_RETENCION_ENUM2[CODIGO_RETENCION_ENUM2["IVA_CIENTO_POR_CIENTO_VOCEADORES"] = 6] = "IVA_CIENTO_POR_CIENTO_VOCEADORES";
  CODIGO_RETENCION_ENUM2[CODIGO_RETENCION_ENUM2["RENTA_DOS_POR_MIL"] = 327] = "RENTA_DOS_POR_MIL";
  CODIGO_RETENCION_ENUM2[CODIGO_RETENCION_ENUM2["RENTA_TRES_POR_MIL"] = 328] = "RENTA_TRES_POR_MIL";
  return CODIGO_RETENCION_ENUM2;
})(CODIGO_RETENCION_ENUM || {});

// src/generator/enums/contribuyente-rimpe.enum.ts
var CONTRIBUYENTE_RIMPE_ENUM = /* @__PURE__ */ ((CONTRIBUYENTE_RIMPE_ENUM2) => {
  CONTRIBUYENTE_RIMPE_ENUM2["RIMPE_GENERAL"] = "CONTRIBUYENTE R\xC9GIMEN RIMPE";
  CONTRIBUYENTE_RIMPE_ENUM2["RIMPE_POPULAR"] = "CONTRIBUYENTE NEGOCIO POPULAR - R\xC9GIMEN RIMPE";
  return CONTRIBUYENTE_RIMPE_ENUM2;
})(CONTRIBUYENTE_RIMPE_ENUM || {});

// src/generator/enums/env.enum.ts
var ENV_ENUM = /* @__PURE__ */ ((ENV_ENUM2) => {
  ENV_ENUM2[ENV_ENUM2["TEST"] = 1] = "TEST";
  ENV_ENUM2[ENV_ENUM2["PROD"] = 2] = "PROD";
  return ENV_ENUM2;
})(ENV_ENUM || {});

// src/generator/enums/identification-code.enum.ts
var IDENTIFICATION_CODE_ENUM = /* @__PURE__ */ ((IDENTIFICATION_CODE_ENUM2) => {
  IDENTIFICATION_CODE_ENUM2["RUC"] = "04";
  IDENTIFICATION_CODE_ENUM2["CEDULA"] = "05";
  IDENTIFICATION_CODE_ENUM2["PASAPORTE"] = "06";
  IDENTIFICATION_CODE_ENUM2["CONSUMIDOR_FINAL"] = "07";
  IDENTIFICATION_CODE_ENUM2["EXTERIOR"] = "08";
  return IDENTIFICATION_CODE_ENUM2;
})(IDENTIFICATION_CODE_ENUM || {});

// src/generator/enums/impuesto-retener.enum.ts
var IMPUESTO_A_RETENER_ENUM = /* @__PURE__ */ ((IMPUESTO_A_RETENER_ENUM2) => {
  IMPUESTO_A_RETENER_ENUM2[IMPUESTO_A_RETENER_ENUM2["IVA_PRESUNTIVO_Y_RENTA"] = 4] = "IVA_PRESUNTIVO_Y_RENTA";
  return IMPUESTO_A_RETENER_ENUM2;
})(IMPUESTO_A_RETENER_ENUM || {});

// src/generator/enums/obligado-contabilidad.enum.ts
var OBLIGADO_CONTABILIDAD_ENUM = /* @__PURE__ */ ((OBLIGADO_CONTABILIDAD_ENUM2) => {
  OBLIGADO_CONTABILIDAD_ENUM2["SI"] = "SI";
  OBLIGADO_CONTABILIDAD_ENUM2["NO"] = "NO";
  return OBLIGADO_CONTABILIDAD_ENUM2;
})(OBLIGADO_CONTABILIDAD_ENUM || {});

// src/generator/enums/payment-method-code.enu,.ts
var PAYMENT_METHOD_CODE_ENUM = /* @__PURE__ */ ((PAYMENT_METHOD_CODE_ENUM2) => {
  PAYMENT_METHOD_CODE_ENUM2["SIN_UTILIZACION_DEL_SISTEMA_FINANCIERO"] = "01";
  PAYMENT_METHOD_CODE_ENUM2["COMPENSACION_DE_DEUDAS"] = "15";
  PAYMENT_METHOD_CODE_ENUM2["TARJETA_DE_DEBITO"] = "16";
  PAYMENT_METHOD_CODE_ENUM2["DINERO_ELECTRONICO"] = "17";
  PAYMENT_METHOD_CODE_ENUM2["TARJETA_PREPAGO"] = "18";
  PAYMENT_METHOD_CODE_ENUM2["TARJETA_DE_CREDITO"] = "19";
  PAYMENT_METHOD_CODE_ENUM2["OTROS_CON_SISTEMA_FINANCIERO"] = "20";
  PAYMENT_METHOD_CODE_ENUM2["ENDOSO_DE_TITULOS"] = "21";
  return PAYMENT_METHOD_CODE_ENUM2;
})(PAYMENT_METHOD_CODE_ENUM || {});

// src/generator/enums/tax-code.enum.ts
var TAX_CODE_ENUM = /* @__PURE__ */ ((TAX_CODE_ENUM2) => {
  TAX_CODE_ENUM2[TAX_CODE_ENUM2["VAT"] = 2] = "VAT";
  TAX_CODE_ENUM2[TAX_CODE_ENUM2["ICE"] = 3] = "ICE";
  TAX_CODE_ENUM2[TAX_CODE_ENUM2["IRBPNR"] = 5] = "IRBPNR";
  return TAX_CODE_ENUM2;
})(TAX_CODE_ENUM || {});

// src/generator/invoice/utils/clave-acceso.util.ts
function p_obtener_codigo_autorizacion(fechaEmision = /* @__PURE__ */ new Date(), tipoComprobante = "factura", ruc = "9999999999999", ambiente = 1 /* TEST */, estab = 1, ptoEmi = 1, secuencial, codigo, tipoEmision = 1) {
  var _a;
  const formattedDate = formatDDMMYYYY(fechaEmision);
  const tipoDoc = (_a = documentTypeCodes[tipoComprobante]) != null ? _a : "01";
  if (!secuencial) throw new Error("El secuencial es obligatorio");
  codigo = codigo != null ? codigo : formatDDMM(fechaEmision) + pad(secuencial, 4).slice(-3) + p_calcular_digito_modulo11(
    formatDDMM(fechaEmision) + pad(secuencial, 3).slice(-3)
  );
  const codigo_autorizacion = formattedDate + pad(tipoDoc, 2) + pad(ruc, 13) + pad(ambiente, 1) + pad(estab, 3) + pad(ptoEmi, 3) + pad(secuencial, 9) + pad(codigo, 8) + pad(tipoEmision, 1);
  const digito_calculado = p_calcular_digito_modulo11(codigo_autorizacion);
  return digito_calculado > -1 ? codigo_autorizacion + digito_calculado : "";
}
function pad(n, width, z = "0") {
  return n.toString().padStart(width, z);
}
function p_calcular_digito_modulo11(numero) {
  if (!/^\d+$/.test(numero)) return -1;
  const digitos = numero.split("").map(Number);
  let suma = digitos.reduce(
    (total, valor, i) => total + valor * (7 - i % 6),
    0
  );
  let digito = 11 - suma % 11;
  return digito === 11 ? 0 : digito === 10 ? 1 : digito;
}

// src/generator/invoice/utils/remove-nulls.util.ts
function removeNullFields(objeto) {
  for (const clave in objeto) {
    if (objeto[clave] === null || objeto[clave] === void 0 || objeto[clave] === "" || typeof objeto[clave] === "object" && Object.keys(objeto[clave]).length === 0) {
      delete objeto[clave];
    } else if (typeof objeto[clave] === "object") {
      removeNullFields(objeto[clave]);
    }
  }
  return objeto;
}

// src/generator/invoice/factory/invoice-xml.factory.ts
var InvoiceXmlFactory = class {
  create(invoice) {
    var _a;
    const {
      detalles,
      infoFactura,
      infoTributaria,
      infoAdicional,
      retenciones
    } = invoice;
    const {
      ambiente,
      dirMatriz,
      estab,
      ptoEmi,
      razonSocial,
      ruc,
      secuencial,
      agenteRetencion,
      contribuyenteRimpe,
      nombreComercial
    } = infoTributaria;
    const {
      dirEstablecimiento,
      identificacionComprador,
      importeTotal,
      pagos,
      propina,
      razonSocialComprador,
      tipoIdentificacionComprador,
      totalConImpuestos,
      totalDescuento,
      totalSinImpuestos,
      contribuyenteEspecial,
      direccionComprador,
      guiaRemision,
      moneda,
      obligadoContabilidad,
      fechaEmision,
      valorRetIva,
      valorRetRenta
    } = infoFactura;
    let fechaClave = new Date(fechaEmision);
    const fechaEmisionParseada = [
      ("0" + fechaClave.getDate()).slice(-2),
      ("0" + (fechaClave.getMonth() + 1)).slice(-2),
      fechaClave.getFullYear()
    ].join("/");
    const tipoEmision = "1";
    const codDoc = pad(documentTypeCodes.factura, 2);
    const clave = p_obtener_codigo_autorizacion(
      fechaClave,
      documentTypeName[1],
      infoTributaria.ruc,
      infoTributaria.ambiente,
      Number(estab),
      Number(ptoEmi),
      infoTributaria.secuencial,
      null,
      Number(tipoEmision)
    );
    let claveAcceso = clave;
    const jsonFactura = {
      factura: {
        $: { id: "comprobante", version: "1.1.0" },
        infoTributaria: {
          ambiente,
          tipoEmision,
          razonSocial,
          nombreComercial,
          ruc,
          claveAcceso,
          codDoc,
          estab,
          ptoEmi,
          secuencial,
          dirMatriz,
          agenteRetencion,
          contribuyenteRimpe
        },
        infoFactura: {
          fechaEmision: fechaEmisionParseada,
          dirEstablecimiento,
          contribuyenteEspecial,
          obligadoContabilidad,
          tipoIdentificacionComprador,
          guiaRemision,
          razonSocialComprador,
          identificacionComprador: tipoIdentificacionComprador === "07" /* CONSUMIDOR_FINAL */ ? "9999999999999" : identificacionComprador,
          direccionComprador,
          totalSinImpuestos: totalSinImpuestos.toFixed(2),
          totalDescuento: totalDescuento.toFixed(2),
          totalConImpuestos: {
            totalImpuesto: []
          },
          propina: propina.toFixed(2),
          importeTotal: importeTotal.toFixed(2),
          moneda: moneda || "DOLAR",
          pagos: {
            pago: []
          },
          valorRetIva: valorRetIva != null ? valorRetIva.toFixed(2) : null,
          valorRetRenta: valorRetRenta != null ? valorRetRenta.toFixed(2) : null
        },
        detalles: {
          detalle: []
        },
        retenciones: {
          retencion: []
        },
        infoAdicional: {
          campoAdicional: []
        }
      }
    };
    const retencion = retenciones == null ? void 0 : retenciones.retencion;
    if (retencion) {
      for (const campo of retencion) {
        jsonFactura.factura.retenciones.retencion.push({
          codigo: campo.codigo,
          codigoPorcentaje: campo.codigoPorcentaje,
          tarifa: campo.tarifa.toFixed(2),
          valor: campo.valor.toFixed(2)
        });
      }
    } else {
      jsonFactura.factura.retenciones = null;
    }
    const campoAdicional = infoAdicional == null ? void 0 : infoAdicional.campoAdicional;
    if (campoAdicional) {
      for (const campo of campoAdicional) {
        jsonFactura.factura.infoAdicional.campoAdicional.push({
          $: { nombre: campo.nombre },
          _: campo.value
        });
      }
    } else {
      jsonFactura.factura.infoAdicional = null;
    }
    for (const impuesto of totalConImpuestos.totalImpuesto) {
      jsonFactura.factura.infoFactura.totalConImpuestos.totalImpuesto.push({
        codigo: impuesto.codigo,
        codigoPorcentaje: impuesto.codigoPorcentaje.toString(),
        descuentoAdicional: impuesto.descuentoAdicional ? impuesto.descuentoAdicional.toFixed(2) : null,
        baseImponible: impuesto.baseImponible.toFixed(2),
        valor: impuesto.valor.toFixed(2)
      });
    }
    for (const pago of pagos.pago) {
      jsonFactura.factura.infoFactura.pagos.pago.push({
        formaPago: pago.formaPago,
        total: Number(pago.total).toFixed(2),
        plazo: pago.plazo,
        unidadTiempo: pago.unidadTiempo
      });
    }
    for (const detalle of detalles.detalle) {
      const detalleFactura = {
        codigoPrincipal: detalle.codigoPrincipal,
        codigoAuxiliar: detalle.codigoAuxiliar,
        descripcion: detalle.descripcion,
        cantidad: detalle.cantidad.toFixed(6),
        precioUnitario: Number(detalle.precioUnitario).toFixed(6),
        descuento: detalle.descuento.toFixed(2),
        precioTotalSinImpuesto: detalle.precioTotalSinImpuesto.toFixed(2),
        detallesAdicionales: { detAdicional: [] },
        impuestos: {
          impuesto: []
        }
      };
      const detAdicionales = (_a = detalle.detallesAdicionales) == null ? void 0 : _a.detAdicional;
      if (detAdicionales) {
        for (const det of detAdicionales) {
          detalleFactura.detallesAdicionales.detAdicional.push({
            $: { nombre: det.nombre, valor: det.valor }
          });
        }
      } else {
        detalleFactura.detallesAdicionales = null;
      }
      for (const impuesto of detalle.impuestos.impuesto) {
        detalleFactura.impuestos.impuesto.push({
          codigo: impuesto.codigo,
          codigoPorcentaje: impuesto.codigoPorcentaje.toString(),
          tarifa: impuesto.tarifa.toString(),
          baseImponible: impuesto.baseImponible.toFixed(2),
          valor: impuesto.valor.toFixed(2)
        });
      }
      jsonFactura.factura.detalles.detalle.push(detalleFactura);
    }
    return { factura: jsonFactura.factura };
  }
};

// src/generator/invoice/invoice.generator.ts
import { Builder } from "xml2js";

// src/generator/invoice/validators/sections/detalles.validator.ts
function validarDetalles(comprobante) {
  const { detalles } = comprobante;
  const errors = [];
  detalles.detalle.forEach((detalle, index) => {
    const ivaPercentageCodes = Object.values(IVA_PERCENTAGE_CODE_ENUM);
    detalle.impuestos.impuesto.forEach((imp, j) => {
      if (imp.codigo === 2 /* VAT */) {
        if (!ivaPercentageCodes.includes(
          imp.codigoPorcentaje.toString()
        )) {
          errors.push(
            `detalle[${index}]: impuesto[${j}]: "codigoPorcentaje" debe ser un valor v\xE1lido de IVA: ${ivaPercentageCodes.join(", ")}.`
          );
        }
      }
    });
  });
  return errors;
}

// src/generator/invoice/validators/sections/info-factura.validator.ts
function validateInfoFactura(comprobante) {
  const { infoFactura } = comprobante;
  const errors = [];
  if (infoFactura.tipoIdentificacionComprador === "05" /* CEDULA */ && infoFactura.identificacionComprador.length !== 10) {
    errors.push(`EL tipo de idenificacion no corresponde con una Cedula`);
  } else if (infoFactura.tipoIdentificacionComprador === "04" /* RUC */ && infoFactura.identificacionComprador.length !== 13) {
    errors.push(`EL tipo de idenificacion no corresponde con un Ruc`);
  }
  const ivaPercentageCodes = Object.values(IVA_PERCENTAGE_CODE_ENUM);
  infoFactura.totalConImpuestos.totalImpuesto.forEach((item, index) => {
    const prefix = `totalImpuesto[${index}]`;
    if (item.codigo === 2 /* VAT */) {
      if (!ivaPercentageCodes.includes(
        item.codigoPorcentaje.toString()
      )) {
        const validLabels = ivaPercentageCodes.map(
          (code) => IVA_PERCENTAGE_LABELS[code]
        ).join(", ");
        errors.push(
          `detalle[${index}]: impuesto[${index}]: "codigoPorcentaje" debe ser un valor v\xE1lido de IVA: ${validLabels}.`
        );
      }
    }
    if (item.codigo !== 2 /* VAT */ && item.descuentoAdicional !== void 0) {
      errors.push(
        `El campo "${prefix}.descuentoAdicional" solo es valido para el codigo 2 (iva)`
      );
    }
  });
  return errors;
}

// src/generator/const/tarifa-retencion-xml.const.ts
var TarifaRetencionXml = {
  // IVA
  [3 /* IVA_CIENTO_POR_CIENTO_RESOLUCION */]: 1,
  [4 /* IVA_DOCE_POR_CIENTO_PRESUNTIVO_EDITORES */]: 0.12,
  [5 /* IVA_CIENTO_POR_CIENTO_DISTRIBUIDORES */]: 100,
  [6 /* IVA_CIENTO_POR_CIENTO_VOCEADORES */]: 100,
  // Renta
  [327 /* RENTA_DOS_POR_MIL */]: 0.2,
  [328 /* RENTA_TRES_POR_MIL */]: 0.2
};

// src/generator/invoice/validators/sections/retenciones.validator.ts
function validarRetenciones(comprobante) {
  const { retenciones } = comprobante;
  const errors = [];
  if (retenciones) {
    retenciones.retencion.forEach((retencion, index) => {
      const prefix = `retencion[${index}]`;
      const tarifaRetencion = TarifaRetencionXml[retencion.codigoPorcentaje];
      if (tarifaRetencion !== retencion.tarifa) {
        errors.push(
          `El campo "${prefix}.tarifa" no es valido para el codigo de porcentaje ${prefix}`
        );
      }
    });
  }
  return errors;
}

// src/generator/invoice/validators/factura-validator.ts
function validateFactura(data) {
  const errors = [];
  errors.push(...validarDetalles(data));
  errors.push(...validateInfoFactura(data));
  errors.push(...validarRetenciones(data));
  return errors;
}

// src/lightweight-validator/strategies/boolean-validation.strategy.ts
var BooleanValidationStrategy = class {
  validate({ key, value }) {
    const errors = [];
    if (typeof value !== "boolean") {
      errors.push(`El campo "${key}" debe ser un boolean.`);
    }
    return errors;
  }
};

// src/lightweight-validator/strategies/date-validation.strategy.ts
var DateValidationStrategy = class {
  validate({ key, value, rule }) {
    const errors = [];
    let parsed;
    if (value instanceof Date) {
      parsed = value;
    } else if (typeof value === "string") {
      parsed = new Date(value);
    } else {
      errors.push(
        rule.message || `El campo "${key}" debe ser una fecha v\xE1lida en formato ISO 8601 (por ejemplo: "2025-06-22T14:30:00Z").`
      );
      return errors;
    }
    if (isNaN(parsed.getTime())) {
      errors.push(
        rule.message || `El campo "${key}" debe ser una fecha v\xE1lida en formato ISO 8601.`
      );
    }
    return errors;
  }
};

// src/lightweight-validator/strategies/enum-validation-strategy.ts
var EnumValidationStrategy = class {
  validate({ key, value, rule }) {
    const errors = [];
    const enumObj = rule.enum;
    if (!enumObj) return errors;
    const allowedValues = Object.entries(enumObj).filter(
      ([enumKey, enumVal]) => typeof enumVal !== "string" || isNaN(Number(enumKey))
    ).map(([, val]) => val);
    if (!allowedValues.includes(value)) {
      const receivedType = typeof value;
      const receivedValue = JSON.stringify(value);
      const formattedAllowed = allowedValues.map((v) => `${JSON.stringify(v)} (${typeof v})`).join(", ");
      errors.push(
        rule.message || `Valor inv\xE1lido para "${key}". Recibido: ${receivedValue} (${receivedType}). Permitidos: ${formattedAllowed}.`
      );
    }
    return errors;
  }
};

// src/lightweight-validator/strategies/number-validation.strategy.ts
var NumberValidationStrategy = class {
  validate({ key, value, rule }) {
    const errors = [];
    if (typeof value !== "number" || isNaN(value)) {
      errors.push(`El campo "${key}" debe ser un n\xFAmero.`);
      return errors;
    }
    if (rule.maxDigits !== void 0) {
      const digits = value.toString().replace(".", "").replace("-", "").length;
      if (digits > rule.maxDigits) {
        errors.push(
          rule.maxDigitsMessage || `El campo "${key}" no puede tener m\xE1s de ${rule.maxDigits} d\xEDgitos en total.`
        );
      }
    }
    if (rule.digits) {
      const [intPart, decPart = ""] = Math.abs(value).toString().split(".");
      const intDigits = intPart.replace(/^0+/, "").length || 1;
      const decDigits = decPart.length;
      if (intDigits > rule.digits.integer || decDigits > rule.digits.fraction) {
        errors.push(
          rule.digitsMessage || `El campo "${key}" debe tener como m\xE1ximo ${rule.digits.integer} d\xEDgitos enteros y ${rule.digits.fraction} decimales.`
        );
      }
    }
    return errors;
  }
};

// src/lightweight-validator/strategies/string-valiation.stategy.ts
var StringValidationStrategy = class {
  validate({ key, value, rule }) {
    const errors = [];
    if (typeof value !== "string") {
      errors.push(`El campo "${key}" debe ser un string.`);
      return errors;
    }
    if (rule.numericOnly && !/^\d+$/.test(value)) {
      errors.push(
        rule.message || `El campo "${key}" solo debe contener n\xFAmeros (sin letras ni s\xEDmbolos).`
      );
      return errors;
    }
    const length = value.length;
    if (rule.exactLength !== void 0 && length !== rule.exactLength) {
      errors.push(
        rule.exactLengthMessage || `El campo "${key}" debe tener exactamente ${rule.exactLength} caracteres.`
      );
    }
    if (rule.minLength !== void 0 && length < rule.minLength) {
      errors.push(
        rule.minLengthMessage || `El campo "${key}" debe tener al menos ${rule.minLength} caracteres.`
      );
    }
    if (rule.maxLength !== void 0 && length > rule.maxLength) {
      errors.push(
        rule.maxLengthMessage || `El campo "${key}" no puede tener m\xE1s de ${rule.maxLength} caracteres.`
      );
    }
    return errors;
  }
};

// src/lightweight-validator/consts/types.validators.const.ts
var typeValidators = {
  string: new StringValidationStrategy(),
  number: new NumberValidationStrategy(),
  boolean: new BooleanValidationStrategy(),
  enum: new EnumValidationStrategy(),
  date: new DateValidationStrategy()
};

// src/lightweight-validator/decorators.ts
function getValidationRules(instance) {
  const rules = {};
  let current = instance;
  while (current && current !== Object.prototype) {
    if (current.__validationRules) {
      Object.assign(rules, current.__validationRules);
    }
    current = Object.getPrototypeOf(current);
  }
  return rules;
}
function IsEnum(enumObj, message) {
  return function(target, context) {
    context.addInitializer(function() {
      if (!this.__validationRules) this.__validationRules = {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "enum",
        enum: enumObj,
        message
      };
    });
  };
}
function IsRequired() {
  return (_, context) => {
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        required: true
      };
    });
  };
}
function IsOptional() {
  return function(target, context) {
    context.addInitializer(function() {
      if (!this.__validationRules) this.__validationRules = {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        required: false
      };
    });
  };
}
function IsString() {
  return function(target, context) {
    context.addInitializer(function() {
      if (!this.__validationRules) this.__validationRules = {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "string"
      };
    });
  };
}
function IsNumber() {
  return function(target, context) {
    context.addInitializer(function() {
      if (!this.__validationRules) this.__validationRules = {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "number"
      };
    });
  };
}
function ValidateNested(type) {
  return (_, context) => {
    if (context.kind !== "field") {
      throw new Error(`ValidateNested solo puede usarse en propiedades`);
    }
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "object",
        nestedType: type
      };
    });
  };
}
function IsArray(itemType) {
  return (_, context) => {
    if (context.kind !== "field") {
      throw new Error(`IsArray solo puede usarse en propiedades`);
    }
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "array",
        arrayItemType: itemType
      };
    });
  };
}
function Length(options) {
  return function(target, context) {
    context.addInitializer(function() {
      if (!this.__validationRules) this.__validationRules = {};
      const rule = this.__validationRules[context.name] || {};
      if (!rule.type) {
        rule.type = "string";
      }
      if (rule.type !== "string") {
        throw new Error(
          `@Length solo puede usarse en propiedades de tipo string`
        );
      }
      this.__validationRules[context.name] = {
        ...rule,
        minLength: options.min,
        maxLength: options.max,
        exactLength: options.exact,
        minLengthMessage: options.minMessage,
        maxLengthMessage: options.maxMessage,
        exactLengthMessage: options.exactMessage
      };
    });
  };
}
function IsNumericString(message) {
  return function(_, context) {
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "string",
        // sigue siendo string
        numericOnly: true,
        message
      };
    });
  };
}
function IsDate(message) {
  return (_, context) => {
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "date",
        message
      };
    });
  };
}
function MaxDigits(max, message) {
  return (_, context) => {
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "number",
        maxDigits: max,
        maxDigitsMessage: message
      };
    });
  };
}
function Digits(options, message) {
  return (_, context) => {
    context.addInitializer(function() {
      this.__validationRules = this.__validationRules || {};
      this.__validationRules[context.name] = {
        ...this.__validationRules[context.name] || {},
        type: "number",
        digits: options,
        digitsMessage: message
      };
    });
  };
}

// src/lightweight-validator/validations/object.validation.ts
function toDecorated(ctor, raw) {
  if (raw === null || raw === void 0) return raw;
  return raw instanceof ctor ? raw : Object.assign(new ctor(), raw);
}
function validateObject(instance, path = "") {
  const errors = [];
  if (instance === null || instance === void 0 || typeof instance !== "object") {
    return errors;
  }
  const rules = getValidationRules(instance);
  if (!rules || Object.keys(rules).length === 0) return errors;
  for (const key in rules) {
    if (!Object.hasOwnProperty.call(rules, key)) continue;
    const fullPath = path ? `${path}.${key}` : key;
    const rule = rules[key];
    let value = instance[key];
    const cleaned = typeof value === "string" ? value.trim() : value;
    if (rule.required && (cleaned === void 0 || cleaned === null || cleaned === "")) {
      errors.push(`El campo "${fullPath}" es obligatorio.`);
      continue;
    }
    if (!rule.required && (value === void 0 || value === null)) {
      continue;
    }
    const strategy = typeValidators[rule.type || ""];
    if (strategy) {
      errors.push(...strategy.validate({ key: fullPath, value, rule }));
      continue;
    }
    switch (rule.type) {
      case "object":
        if (value === null) {
          errors.push(`El campo "${fullPath}" debe ser un objeto.`);
        } else if (rule.nestedType) {
          try {
            const nestedInstance = toDecorated(rule.nestedType(), value);
            errors.push(...validateObject(nestedInstance, fullPath));
          } catch (e) {
            errors.push(`Error en campo "${fullPath}": ${e.message}`);
          }
        }
        break;
      case "array":
        if (!Array.isArray(value) || value.length === 0) {
          errors.push(`El campo "${fullPath}" debe ser un arreglo con datos.`);
        } else if (rule.arrayItemType) {
          value.forEach((item, index) => {
            const itemPath = `${fullPath}[${index}]`;
            if (item === null || item === void 0) {
              errors.push(`Elemento ${itemPath} no puede ser nulo`);
            } else {
              try {
                const itemInstance = toDecorated(rule.arrayItemType(), item);
                errors.push(...validateObject(itemInstance, itemPath));
              } catch (e) {
                errors.push(`Error en elemento ${itemPath}: ${e.message}`);
              }
            }
          });
        }
        break;
    }
  }
  return errors;
}

// src/generator/exceptions/validation.exception.ts
var ValidationException = class extends Error {
  constructor(errors) {
    super("Error de validaci\xF3n");
    this.errors = errors;
  }
};

// src/generator/invoice/models/comprobante.model.ts
var _contribuyenteRimpe_dec, _agenteRetencion_dec, _dirMatriz_dec, _secuencial_dec, _ptoEmi_dec, _estab_dec, _ruc_dec, _nombreComercial_dec, _razonSocial_dec, _ambiente_dec, _init;
_ambiente_dec = [IsRequired(), IsEnum(ENV_ENUM)], _razonSocial_dec = [IsString(), Length({ max: 300 }), IsRequired()], _nombreComercial_dec = [IsString(), Length({ max: 300 }), IsOptional()], _ruc_dec = [IsString(), Length({ exact: 13 }), IsNumericString(), IsRequired()], _estab_dec = [IsString(), Length({ exact: 3 }), IsNumericString(), IsRequired()], _ptoEmi_dec = [IsString(), Length({ exact: 3 }), IsNumericString(), IsRequired()], _secuencial_dec = [IsString(), Length({ exact: 9 }), IsNumericString(), IsRequired()], _dirMatriz_dec = [IsString(), Length({ max: 300 }), IsRequired()], _agenteRetencion_dec = [IsString(), Length({ min: 1, max: 8 }), IsNumericString(), IsOptional()], _contribuyenteRimpe_dec = [IsEnum(CONTRIBUYENTE_RIMPE_ENUM), IsOptional()];
var InfoTributariaModel = class {
  constructor() {
    this.ambiente = __runInitializers(_init, 8, this), __runInitializers(_init, 11, this);
    this.razonSocial = __runInitializers(_init, 12, this), __runInitializers(_init, 15, this);
    this.nombreComercial = __runInitializers(_init, 16, this), __runInitializers(_init, 19, this);
    this.ruc = __runInitializers(_init, 20, this), __runInitializers(_init, 23, this);
    this.estab = __runInitializers(_init, 24, this), __runInitializers(_init, 27, this);
    this.ptoEmi = __runInitializers(_init, 28, this), __runInitializers(_init, 31, this);
    this.secuencial = __runInitializers(_init, 32, this), __runInitializers(_init, 35, this);
    this.dirMatriz = __runInitializers(_init, 36, this), __runInitializers(_init, 39, this);
    this.agenteRetencion = __runInitializers(_init, 40, this), __runInitializers(_init, 43, this);
    this.contribuyenteRimpe = __runInitializers(_init, 44, this), __runInitializers(_init, 47, this);
  }
};
_init = __decoratorStart(null);
__decorateElement(_init, 5, "ambiente", _ambiente_dec, InfoTributariaModel);
__decorateElement(_init, 5, "razonSocial", _razonSocial_dec, InfoTributariaModel);
__decorateElement(_init, 5, "nombreComercial", _nombreComercial_dec, InfoTributariaModel);
__decorateElement(_init, 5, "ruc", _ruc_dec, InfoTributariaModel);
__decorateElement(_init, 5, "estab", _estab_dec, InfoTributariaModel);
__decorateElement(_init, 5, "ptoEmi", _ptoEmi_dec, InfoTributariaModel);
__decorateElement(_init, 5, "secuencial", _secuencial_dec, InfoTributariaModel);
__decorateElement(_init, 5, "dirMatriz", _dirMatriz_dec, InfoTributariaModel);
__decorateElement(_init, 5, "agenteRetencion", _agenteRetencion_dec, InfoTributariaModel);
__decorateElement(_init, 5, "contribuyenteRimpe", _contribuyenteRimpe_dec, InfoTributariaModel);
__decoratorMetadata(_init, InfoTributariaModel);
var _descuentoAdicional_dec, _valor_dec, _baseImponible_dec, _codigoPorcentaje_dec, _codigo_dec, _init2;
_codigo_dec = [IsEnum(TAX_CODE_ENUM), IsRequired()], _codigoPorcentaje_dec = [IsNumber(), MaxDigits(4), IsRequired()], _baseImponible_dec = [IsNumber(), MaxDigits(14), IsRequired()], _valor_dec = [IsNumber(), MaxDigits(14), IsRequired()], _descuentoAdicional_dec = [IsNumber(), MaxDigits(14), IsOptional()];
var TotalImpuestoModel = class {
  constructor() {
    this.codigo = __runInitializers(_init2, 8, this), __runInitializers(_init2, 11, this);
    this.codigoPorcentaje = __runInitializers(_init2, 12, this), __runInitializers(_init2, 15, this);
    this.baseImponible = __runInitializers(_init2, 16, this), __runInitializers(_init2, 19, this);
    this.valor = __runInitializers(_init2, 20, this), __runInitializers(_init2, 23, this);
    this.descuentoAdicional = __runInitializers(_init2, 24, this), __runInitializers(_init2, 27, this);
  }
  //TODO: SOLO PARA EL CODIGO TAX_CODE_ENUM VAT= 2
};
_init2 = __decoratorStart(null);
__decorateElement(_init2, 5, "codigo", _codigo_dec, TotalImpuestoModel);
__decorateElement(_init2, 5, "codigoPorcentaje", _codigoPorcentaje_dec, TotalImpuestoModel);
__decorateElement(_init2, 5, "baseImponible", _baseImponible_dec, TotalImpuestoModel);
__decorateElement(_init2, 5, "valor", _valor_dec, TotalImpuestoModel);
__decorateElement(_init2, 5, "descuentoAdicional", _descuentoAdicional_dec, TotalImpuestoModel);
__decoratorMetadata(_init2, TotalImpuestoModel);
var _totalImpuesto_dec, _init3;
_totalImpuesto_dec = [IsArray(() => TotalImpuestoModel), IsRequired()];
var TotalConImpuestosModel = class {
  constructor() {
    this.totalImpuesto = __runInitializers(_init3, 8, this), __runInitializers(_init3, 11, this);
  }
};
_init3 = __decoratorStart(null);
__decorateElement(_init3, 5, "totalImpuesto", _totalImpuesto_dec, TotalConImpuestosModel);
__decoratorMetadata(_init3, TotalConImpuestosModel);
var _unidadTiempo_dec, _plazo_dec, _total_dec, _formaPago_dec, _init4;
_formaPago_dec = [IsEnum(PAYMENT_METHOD_CODE_ENUM), IsRequired()], _total_dec = [IsNumber(), MaxDigits(14), IsRequired()], _plazo_dec = [IsNumber(), MaxDigits(14), IsOptional()], _unidadTiempo_dec = [IsString(), Length({ max: 10 }), IsOptional()];
var PagoModel = class {
  constructor() {
    this.formaPago = __runInitializers(_init4, 8, this), __runInitializers(_init4, 11, this);
    this.total = __runInitializers(_init4, 12, this), __runInitializers(_init4, 15, this);
    this.plazo = __runInitializers(_init4, 16, this), __runInitializers(_init4, 19, this);
    this.unidadTiempo = __runInitializers(_init4, 20, this), __runInitializers(_init4, 23, this);
  }
};
_init4 = __decoratorStart(null);
__decorateElement(_init4, 5, "formaPago", _formaPago_dec, PagoModel);
__decorateElement(_init4, 5, "total", _total_dec, PagoModel);
__decorateElement(_init4, 5, "plazo", _plazo_dec, PagoModel);
__decorateElement(_init4, 5, "unidadTiempo", _unidadTiempo_dec, PagoModel);
__decoratorMetadata(_init4, PagoModel);
var _pago_dec, _init5;
_pago_dec = [IsArray(() => PagoModel), IsRequired()];
var PagosModel = class {
  constructor() {
    this.pago = __runInitializers(_init5, 8, this), __runInitializers(_init5, 11, this);
  }
};
_init5 = __decoratorStart(null);
__decorateElement(_init5, 5, "pago", _pago_dec, PagosModel);
__decoratorMetadata(_init5, PagosModel);
var _valorRetRenta_dec, _valorRetIva_dec, _pagos_dec, _moneda_dec, _importeTotal_dec, _propina_dec, _totalConImpuestos_dec, _totalDescuento_dec, _totalSinImpuestos_dec, _direccionComprador_dec, _identificacionComprador_dec, _razonSocialComprador_dec, _guiaRemision_dec, _tipoIdentificacionComprador_dec, _obligadoContabilidad_dec, _contribuyenteEspecial_dec, _dirEstablecimiento_dec, _fechaEmision_dec, _init6;
_fechaEmision_dec = [IsDate(), IsRequired()], _dirEstablecimiento_dec = [IsString(), Length({ max: 300 }), IsOptional()], _contribuyenteEspecial_dec = [IsString(), Length({ min: 3, max: 13 }), IsOptional()], _obligadoContabilidad_dec = [IsEnum(OBLIGADO_CONTABILIDAD_ENUM), IsOptional()], _tipoIdentificacionComprador_dec = [IsEnum(IDENTIFICATION_CODE_ENUM), IsRequired()], _guiaRemision_dec = [IsString(), Length({ exact: 17 }), IsOptional()], _razonSocialComprador_dec = [IsString(), Length({ max: 300 }), IsRequired()], _identificacionComprador_dec = [IsString(), Length({ max: 20 }), IsRequired()], _direccionComprador_dec = [IsString(), Length({ max: 300 }), IsOptional()], _totalSinImpuestos_dec = [IsNumber(), MaxDigits(14), IsRequired()], _totalDescuento_dec = [IsNumber(), MaxDigits(14), IsRequired()], _totalConImpuestos_dec = [ValidateNested(() => TotalConImpuestosModel), IsRequired()], _propina_dec = [IsNumber(), MaxDigits(14), IsRequired()], _importeTotal_dec = [IsNumber(), MaxDigits(14), IsRequired()], _moneda_dec = [IsString(), MaxDigits(15), IsOptional()], _pagos_dec = [ValidateNested(() => PagosModel), IsRequired()], _valorRetIva_dec = [IsNumber(), Digits({ integer: 15, fraction: 2 }), IsOptional()], _valorRetRenta_dec = [IsNumber(), Digits({ integer: 15, fraction: 2 }), IsOptional()];
var InfoFacturaModel = class {
  constructor() {
    this.fechaEmision = __runInitializers(_init6, 8, this), __runInitializers(_init6, 11, this);
    this.dirEstablecimiento = __runInitializers(_init6, 12, this), __runInitializers(_init6, 15, this);
    this.contribuyenteEspecial = __runInitializers(_init6, 16, this), __runInitializers(_init6, 19, this);
    this.obligadoContabilidad = __runInitializers(_init6, 20, this), __runInitializers(_init6, 23, this);
    this.tipoIdentificacionComprador = __runInitializers(_init6, 24, this), __runInitializers(_init6, 27, this);
    this.guiaRemision = __runInitializers(_init6, 28, this), __runInitializers(_init6, 31, this);
    this.razonSocialComprador = __runInitializers(_init6, 32, this), __runInitializers(_init6, 35, this);
    this.identificacionComprador = __runInitializers(_init6, 36, this), __runInitializers(_init6, 39, this);
    this.direccionComprador = __runInitializers(_init6, 40, this), __runInitializers(_init6, 43, this);
    this.totalSinImpuestos = __runInitializers(_init6, 44, this), __runInitializers(_init6, 47, this);
    this.totalDescuento = __runInitializers(_init6, 48, this), __runInitializers(_init6, 51, this);
    this.totalConImpuestos = __runInitializers(_init6, 52, this), __runInitializers(_init6, 55, this);
    this.propina = __runInitializers(_init6, 56, this), __runInitializers(_init6, 59, this);
    this.importeTotal = __runInitializers(_init6, 60, this), __runInitializers(_init6, 63, this);
    this.moneda = __runInitializers(_init6, 64, this), __runInitializers(_init6, 67, this);
    this.pagos = __runInitializers(_init6, 68, this), __runInitializers(_init6, 71, this);
    this.valorRetIva = __runInitializers(_init6, 72, this), __runInitializers(_init6, 75, this);
    this.valorRetRenta = __runInitializers(_init6, 76, this), __runInitializers(_init6, 79, this);
  }
};
_init6 = __decoratorStart(null);
__decorateElement(_init6, 5, "fechaEmision", _fechaEmision_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "dirEstablecimiento", _dirEstablecimiento_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "contribuyenteEspecial", _contribuyenteEspecial_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "obligadoContabilidad", _obligadoContabilidad_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "tipoIdentificacionComprador", _tipoIdentificacionComprador_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "guiaRemision", _guiaRemision_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "razonSocialComprador", _razonSocialComprador_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "identificacionComprador", _identificacionComprador_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "direccionComprador", _direccionComprador_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "totalSinImpuestos", _totalSinImpuestos_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "totalDescuento", _totalDescuento_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "totalConImpuestos", _totalConImpuestos_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "propina", _propina_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "importeTotal", _importeTotal_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "moneda", _moneda_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "pagos", _pagos_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "valorRetIva", _valorRetIva_dec, InfoFacturaModel);
__decorateElement(_init6, 5, "valorRetRenta", _valorRetRenta_dec, InfoFacturaModel);
__decoratorMetadata(_init6, InfoFacturaModel);
var _valor_dec2, _nombre_dec, _init7;
_nombre_dec = [IsString(), Length({ max: 300 }), IsRequired()], _valor_dec2 = [IsString(), Length({ max: 300 }), IsRequired()];
var DetAdicionalModel = class {
  constructor() {
    this.nombre = __runInitializers(_init7, 8, this), __runInitializers(_init7, 11, this);
    this.valor = __runInitializers(_init7, 12, this), __runInitializers(_init7, 15, this);
  }
};
_init7 = __decoratorStart(null);
__decorateElement(_init7, 5, "nombre", _nombre_dec, DetAdicionalModel);
__decorateElement(_init7, 5, "valor", _valor_dec2, DetAdicionalModel);
__decoratorMetadata(_init7, DetAdicionalModel);
var _valor_dec3, _baseImponible_dec2, _tarifa_dec, _codigoPorcentaje_dec2, _codigo_dec2, _init8;
_codigo_dec2 = [IsEnum(TAX_CODE_ENUM), IsRequired()], _codigoPorcentaje_dec2 = [IsNumber(), MaxDigits(4), IsRequired()], _tarifa_dec = [IsNumber(), Digits({ integer: 2, fraction: 2 }), IsRequired()], _baseImponible_dec2 = [IsNumber(), MaxDigits(14), IsRequired()], _valor_dec3 = [IsNumber(), MaxDigits(14), IsRequired()];
var ImpuestoDetalleModel = class {
  constructor() {
    this.codigo = __runInitializers(_init8, 8, this), __runInitializers(_init8, 11, this);
    this.codigoPorcentaje = __runInitializers(_init8, 12, this), __runInitializers(_init8, 15, this);
    this.tarifa = __runInitializers(_init8, 16, this), __runInitializers(_init8, 19, this);
    this.baseImponible = __runInitializers(_init8, 20, this), __runInitializers(_init8, 23, this);
    this.valor = __runInitializers(_init8, 24, this), __runInitializers(_init8, 27, this);
  }
};
_init8 = __decoratorStart(null);
__decorateElement(_init8, 5, "codigo", _codigo_dec2, ImpuestoDetalleModel);
__decorateElement(_init8, 5, "codigoPorcentaje", _codigoPorcentaje_dec2, ImpuestoDetalleModel);
__decorateElement(_init8, 5, "tarifa", _tarifa_dec, ImpuestoDetalleModel);
__decorateElement(_init8, 5, "baseImponible", _baseImponible_dec2, ImpuestoDetalleModel);
__decorateElement(_init8, 5, "valor", _valor_dec3, ImpuestoDetalleModel);
__decoratorMetadata(_init8, ImpuestoDetalleModel);
var _detAdicional_dec, _init9;
_detAdicional_dec = [IsArray(() => DetAdicionalModel), IsRequired()];
var DetallesAdicionalesModel = class {
  constructor() {
    this.detAdicional = __runInitializers(_init9, 8, this), __runInitializers(_init9, 11, this);
  }
};
_init9 = __decoratorStart(null);
__decorateElement(_init9, 5, "detAdicional", _detAdicional_dec, DetallesAdicionalesModel);
__decoratorMetadata(_init9, DetallesAdicionalesModel);
var _impuesto_dec, _init10;
_impuesto_dec = [IsArray(() => ImpuestoDetalleModel), IsRequired()];
var ImpuestosModel = class {
  constructor() {
    this.impuesto = __runInitializers(_init10, 8, this), __runInitializers(_init10, 11, this);
  }
};
_init10 = __decoratorStart(null);
__decorateElement(_init10, 5, "impuesto", _impuesto_dec, ImpuestosModel);
__decoratorMetadata(_init10, ImpuestosModel);
var _impuestos_dec, _detallesAdicionales_dec, _precioTotalSinImpuesto_dec, _descuento_dec, _precioUnitario_dec, _cantidad_dec, _descripcion_dec, _codigoAuxiliar_dec, _codigoPrincipal_dec, _init11;
_codigoPrincipal_dec = [IsString(), Length({ max: 25 }), IsRequired()], _codigoAuxiliar_dec = [IsString(), Length({ max: 25 }), IsOptional()], _descripcion_dec = [IsString(), Length({ max: 300 }), IsRequired()], _cantidad_dec = [IsNumber(), MaxDigits(14), IsRequired()], _precioUnitario_dec = [IsNumber(), MaxDigits(14), IsRequired()], _descuento_dec = [IsNumber(), MaxDigits(14), IsRequired()], _precioTotalSinImpuesto_dec = [IsNumber(), MaxDigits(14), IsRequired()], _detallesAdicionales_dec = [ValidateNested(() => DetallesAdicionalesModel), IsOptional()], _impuestos_dec = [ValidateNested(() => ImpuestosModel), IsRequired()];
var DetalleModel = class {
  constructor() {
    this.codigoPrincipal = __runInitializers(_init11, 8, this), __runInitializers(_init11, 11, this);
    this.codigoAuxiliar = __runInitializers(_init11, 12, this), __runInitializers(_init11, 15, this);
    this.descripcion = __runInitializers(_init11, 16, this), __runInitializers(_init11, 19, this);
    this.cantidad = __runInitializers(_init11, 20, this), __runInitializers(_init11, 23, this);
    this.precioUnitario = __runInitializers(_init11, 24, this), __runInitializers(_init11, 27, this);
    this.descuento = __runInitializers(_init11, 28, this), __runInitializers(_init11, 31, this);
    this.precioTotalSinImpuesto = __runInitializers(_init11, 32, this), __runInitializers(_init11, 35, this);
    this.detallesAdicionales = __runInitializers(_init11, 36, this), __runInitializers(_init11, 39, this);
    this.impuestos = __runInitializers(_init11, 40, this), __runInitializers(_init11, 43, this);
  }
};
_init11 = __decoratorStart(null);
__decorateElement(_init11, 5, "codigoPrincipal", _codigoPrincipal_dec, DetalleModel);
__decorateElement(_init11, 5, "codigoAuxiliar", _codigoAuxiliar_dec, DetalleModel);
__decorateElement(_init11, 5, "descripcion", _descripcion_dec, DetalleModel);
__decorateElement(_init11, 5, "cantidad", _cantidad_dec, DetalleModel);
__decorateElement(_init11, 5, "precioUnitario", _precioUnitario_dec, DetalleModel);
__decorateElement(_init11, 5, "descuento", _descuento_dec, DetalleModel);
__decorateElement(_init11, 5, "precioTotalSinImpuesto", _precioTotalSinImpuesto_dec, DetalleModel);
__decorateElement(_init11, 5, "detallesAdicionales", _detallesAdicionales_dec, DetalleModel);
__decorateElement(_init11, 5, "impuestos", _impuestos_dec, DetalleModel);
__decoratorMetadata(_init11, DetalleModel);
var _value_dec, _nombre_dec2, _init12;
_nombre_dec2 = [IsString(), Length({ max: 300 }), IsRequired()], _value_dec = [IsString(), Length({ max: 300 }), IsRequired()];
var CampoAdicionalModel = class {
  constructor() {
    this.nombre = __runInitializers(_init12, 8, this), __runInitializers(_init12, 11, this);
    this.value = __runInitializers(_init12, 12, this), __runInitializers(_init12, 15, this);
  }
};
_init12 = __decoratorStart(null);
__decorateElement(_init12, 5, "nombre", _nombre_dec2, CampoAdicionalModel);
__decorateElement(_init12, 5, "value", _value_dec, CampoAdicionalModel);
__decoratorMetadata(_init12, CampoAdicionalModel);
var _campoAdicional_dec, _init13;
_campoAdicional_dec = [IsArray(() => CampoAdicionalModel), IsRequired()];
var InfoAdicionalModel = class {
  constructor() {
    this.campoAdicional = __runInitializers(_init13, 8, this), __runInitializers(_init13, 11, this);
  }
};
_init13 = __decoratorStart(null);
__decorateElement(_init13, 5, "campoAdicional", _campoAdicional_dec, InfoAdicionalModel);
__decoratorMetadata(_init13, InfoAdicionalModel);
var _detalle_dec, _init14;
_detalle_dec = [IsArray(() => DetalleModel), IsRequired()];
var DetallesModel = class {
  constructor() {
    this.detalle = __runInitializers(_init14, 8, this), __runInitializers(_init14, 11, this);
  }
};
_init14 = __decoratorStart(null);
__decorateElement(_init14, 5, "detalle", _detalle_dec, DetallesModel);
__decoratorMetadata(_init14, DetallesModel);
var _retencion_dec, _init15;
_retencion_dec = [IsArray(() => RetencionModel), IsRequired()];
var RetencionesModel = class {
  constructor() {
    this.retencion = __runInitializers(_init15, 8, this), __runInitializers(_init15, 11, this);
  }
};
_init15 = __decoratorStart(null);
__decorateElement(_init15, 5, "retencion", _retencion_dec, RetencionesModel);
__decoratorMetadata(_init15, RetencionesModel);
var _valor_dec4, _tarifa_dec2, _codigoPorcentaje_dec3, _codigo_dec3, _init16;
_codigo_dec3 = [IsEnum(IMPUESTO_A_RETENER_ENUM), IsRequired()], _codigoPorcentaje_dec3 = [IsEnum(CODIGO_RETENCION_ENUM), IsRequired()], _tarifa_dec2 = [IsNumber(), Digits({ integer: 3, fraction: 2 }), IsRequired()], _valor_dec4 = [IsNumber(), Digits({ integer: 12, fraction: 2 }), IsRequired()];
var RetencionModel = class {
  constructor() {
    this.codigo = __runInitializers(_init16, 8, this), __runInitializers(_init16, 11, this);
    this.codigoPorcentaje = __runInitializers(_init16, 12, this), __runInitializers(_init16, 15, this);
    this.tarifa = __runInitializers(_init16, 16, this), __runInitializers(_init16, 19, this);
    this.valor = __runInitializers(_init16, 20, this), __runInitializers(_init16, 23, this);
  }
};
_init16 = __decoratorStart(null);
__decorateElement(_init16, 5, "codigo", _codigo_dec3, RetencionModel);
__decorateElement(_init16, 5, "codigoPorcentaje", _codigoPorcentaje_dec3, RetencionModel);
__decorateElement(_init16, 5, "tarifa", _tarifa_dec2, RetencionModel);
__decorateElement(_init16, 5, "valor", _valor_dec4, RetencionModel);
__decoratorMetadata(_init16, RetencionModel);
var _infoAdicional_dec, _retenciones_dec, _detalles_dec, _infoFactura_dec, _infoTributaria_dec, _init17;
_infoTributaria_dec = [ValidateNested(() => InfoTributariaModel), IsRequired()], _infoFactura_dec = [ValidateNested(() => InfoFacturaModel), IsRequired()], _detalles_dec = [ValidateNested(() => DetallesModel), IsRequired()], _retenciones_dec = [ValidateNested(() => RetencionesModel), IsOptional()], _infoAdicional_dec = [ValidateNested(() => InfoAdicionalModel), IsOptional()];
var ComprobanteModel = class {
  constructor() {
    this.infoTributaria = __runInitializers(_init17, 8, this), __runInitializers(_init17, 11, this);
    this.infoFactura = __runInitializers(_init17, 12, this), __runInitializers(_init17, 15, this);
    this.detalles = __runInitializers(_init17, 16, this), __runInitializers(_init17, 19, this);
    this.retenciones = __runInitializers(_init17, 20, this), __runInitializers(_init17, 23, this);
    this.infoAdicional = __runInitializers(_init17, 24, this), __runInitializers(_init17, 27, this);
  }
};
_init17 = __decoratorStart(null);
__decorateElement(_init17, 5, "infoTributaria", _infoTributaria_dec, ComprobanteModel);
__decorateElement(_init17, 5, "infoFactura", _infoFactura_dec, ComprobanteModel);
__decorateElement(_init17, 5, "detalles", _detalles_dec, ComprobanteModel);
__decorateElement(_init17, 5, "retenciones", _retenciones_dec, ComprobanteModel);
__decorateElement(_init17, 5, "infoAdicional", _infoAdicional_dec, ComprobanteModel);
__decoratorMetadata(_init17, ComprobanteModel);

// src/generator/invoice/invoice.generator.ts
async function generateXmlInvoice(invoice) {
  const user = toDecorated(ComprobanteModel, invoice);
  const errorsObject = validateObject(user);
  const errorsValidate = validateFactura(invoice);
  const errors = [...errorsObject, ...errorsValidate];
  if (errors.length > 0) {
    throw new ValidationException(errors);
  }
  const factura = new InvoiceXmlFactory().create(invoice);
  const cleaned = removeNullFields(factura);
  const xml = new Builder({ renderOpts: { pretty: true } }).buildObject(
    cleaned
  );
  return {
    generatedXml: xml,
    invoiceJson: cleaned
  };
}

// src/sri/const/sri-urls.ts
var SRI_URLS = {
  test: {
    recepcion: "https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl",
    autorizacion: "https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl"
  },
  prod: {
    recepcion: "https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl",
    autorizacion: "https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl"
  }
};

// src/sri/helpers/soap-client.ts
import * as soap from "soap";
async function createSoapClient(wsdlUrl) {
  return await soap.createClientAsync(wsdlUrl);
}

// src/sri/helpers/normalize-mensajes.helper.ts
function normalizeSriMessages(message) {
  if (!message) return null;
  return Array.isArray(message) ? message : [message];
}

// src/sri/exceptions/base-sri.error.ts
var BaseSRIError = class extends Error {
  constructor(params) {
    var _a;
    const fullMessage = (_a = params.customMessage) != null ? _a : `[SRI-${params.tipo}] ${params.mensaje} (ID ${params.identificador}) - ${params.informacionAdicional}`;
    super(fullMessage);
    this.estado = params.estado;
    this.identificador = params.identificador;
    this.mensajeSRI = params.mensaje;
    this.informacionAdicional = params.informacionAdicional;
    this.tipo = params.tipo;
    this.claveAcceso = params.claveAcceso;
  }
};
var SRIError = class extends Error {
  constructor(message) {
    super(message);
    this.name = "SRIError";
  }
};

// src/sri/exceptions/sri-autorizacion.error.ts
var SRIAutorizacionError = class extends Error {
  constructor(params) {
    const msg = `[SRI-${params.tipo}] ${params.mensaje} (ID ${params.identificador}) - ${params.informacionAdicional}`;
    super(msg);
    this.estado = params.estado;
    this.identificador = params.identificador;
    this.mensajeSRI = params.mensaje;
    this.informacionAdicional = params.informacionAdicional;
    this.tipo = params.tipo;
    this.claveAcceso = params.claveAcceso;
    this.ambiente = params.ambiente;
    this.comprobanteXml = params.comprobanteXml;
  }
};
var SRIUnauthorizedError = class extends SRIError {
  constructor(estado) {
    super(`Estado del comprobante: ${estado}`);
    this.estado = estado;
    this.name = "SRIUnauthorizedError";
  }
};

// src/sri/services/sri-autorizacion.service.ts
async function authorizeXml(data) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
  const { claveAcceso, env } = data;
  const client = await createSoapClient(SRI_URLS[env].autorizacion);
  const [result] = await client.autorizacionComprobanteAsync({
    claveAccesoComprobante: claveAcceso
  });
  const respuesta = result == null ? void 0 : result.RespuestaAutorizacionComprobante;
  const autorizacion = (_a = respuesta == null ? void 0 : respuesta.autorizaciones) == null ? void 0 : _a.autorizacion;
  if (!autorizacion || autorizacion.length === 0) {
    throw new Error("No se recibi\xF3 informaci\xF3n de autorizaci\xF3n del SRI");
  }
  const estado = autorizacion.estado;
  if (estado === "AUTORIZADO") {
    return {
      claveAcceso: autorizacion.claveAcceso,
      estadoAutorizacion: estado,
      comprobante: autorizacion.comprobante,
      rucEmisor: (_b = autorizacion.numeroAutorizacion) != null ? _b : "",
      fechaAutorizacion: autorizacion.fechaAutorizacion,
      ambiente: autorizacion.ambiente,
      mensajes: normalizeSriMessages((_c = autorizacion.mensajes) == null ? void 0 : _c.mensaje)
    };
  }
  if (estado === "NO AUTORIZADO" || estado === "RECHAZADA") {
    const mensaje = (_d = autorizacion.mensajes) == null ? void 0 : _d.mensaje;
    const mensajeFinal = Array.isArray(mensaje) ? mensaje[0] : mensaje;
    if (mensajeFinal) {
      throw new SRIAutorizacionError({
        estado,
        identificador: (_e = mensajeFinal.identificador) != null ? _e : "SIN_IDENTIFICADOR",
        mensaje: (_f = mensajeFinal.mensaje) != null ? _f : "Mensaje no disponible",
        informacionAdicional: (_g = mensajeFinal.informacionAdicional) != null ? _g : "Sin informaci\xF3n adicional",
        tipo: (_h = mensajeFinal.tipo) != null ? _h : "ERROR",
        claveAcceso: (_i = respuesta.claveAccesoConsultada) != null ? _i : claveAcceso,
        ambiente: autorizacion.ambiente,
        comprobanteXml: autorizacion.comprobante
      });
    }
    throw new SRIUnauthorizedError(estado);
  }
  throw new SRIUnauthorizedError(estado);
}

// src/sri/exceptions/sri-rejected.error.ts
var SRIRejectedError = class extends BaseSRIError {
  constructor(params) {
    super(params);
  }
};

// src/sri/services/sri-recepcion.service.ts
async function validateXml(data) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
  const { env, xml } = data;
  const client = await createSoapClient(SRI_URLS[env].recepcion);
  const xmlBase64 = uint8ArrayToBase64(xml);
  let result;
  try {
    [result] = await client.validarComprobanteAsync({ xml: xmlBase64 });
  } catch (error) {
    throw new Error(`Error SOAP al validar comprobante: ${error.message}`);
  }
  const respuesta = result == null ? void 0 : result.RespuestaRecepcionComprobante;
  if (!respuesta) {
    throw new Error(
      "Respuesta inv\xE1lida del SRI (sin 'respuestaRecepcionComprobante')"
    );
  }
  const comprobante = Array.isArray((_a = respuesta.comprobantes) == null ? void 0 : _a.comprobante) ? respuesta.comprobantes.comprobante[0] : (_b = respuesta.comprobantes) == null ? void 0 : _b.comprobante;
  const mensaje = (_c = comprobante == null ? void 0 : comprobante.mensajes) == null ? void 0 : _c.mensaje;
  if (respuesta.estado !== "RECIBIDA") {
    if (mensaje) {
      throw new SRIRejectedError({
        estado: respuesta.estado,
        identificador: (_d = mensaje.identificador) != null ? _d : "SIN_IDENTIFICADOR",
        mensaje: (_e = mensaje.mensaje) != null ? _e : "Mensaje no disponible",
        informacionAdicional: (_f = mensaje.informacionAdicional) != null ? _f : "Sin informaci\xF3n adicional",
        tipo: (_g = mensaje.tipo) != null ? _g : "ERROR",
        claveAcceso: (_h = comprobante == null ? void 0 : comprobante.claveAcceso) != null ? _h : "SIN_CLAVE"
      });
    }
    throw new Error(
      "Comprobante no recibido y sin mensaje explicativo del SRI"
    );
  }
  return {
    estado: respuesta.estado,
    mensaje: (_i = mensaje == null ? void 0 : mensaje.mensaje) != null ? _i : "Comprobante recibido correctamente"
  };
}

// src/generator/invoice/models/invoice-sri-builder.model.ts
var Retenciones = class {
};
var Retencion = class {
};
export {
  BaseSRIError,
  CODIGO_RETENCION_ENUM,
  CONTRIBUYENTE_RIMPE_ENUM,
  CampoAdicionalModel,
  CodigoPais,
  ComprobanteModel,
  DetAdicionalModel,
  DetalleModel,
  DetallesAdicionalesModel,
  DetallesModel,
  ENV_ENUM,
  IDENTIFICATION_CODE_ENUM,
  IMPUESTO_A_RETENER_ENUM,
  IVA_PERCENTAGE_CODE_ENUM,
  ImpuestoDetalleModel,
  ImpuestosModel,
  InfoAdicionalModel,
  InfoFacturaModel,
  InfoTributariaModel,
  OBLIGADO_CONTABILIDAD_ENUM,
  PAYMENT_METHOD_CODE_ENUM,
  PagoModel,
  PagosModel,
  Retencion,
  RetencionModel,
  Retenciones,
  RetencionesModel,
  SRIAutorizacionError,
  SRIError,
  SRIRejectedError,
  SRIUnauthorizedError,
  SRI_URLS,
  TAX_CODE_ENUM,
  TotalConImpuestosModel,
  TotalImpuestoModel,
  authorizeXml,
  generateXmlInvoice,
  signXml,
  validateXml
};