dgii-ts 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.en.md +39 -3
  2. package/README.md +40 -3
  3. package/dist/bulk.cjs +8 -2
  4. package/dist/bulk.d.cts +48 -5
  5. package/dist/bulk.d.ts +48 -5
  6. package/dist/bulk.js +7 -1
  7. package/dist/{chunk-5FZ4F5UR.cjs → chunk-6ZRPVQPP.cjs} +20 -15
  8. package/dist/{chunk-HRRYZUKI.js → chunk-7ILLRYE4.js} +114 -11
  9. package/dist/{chunk-JBKAE66C.cjs → chunk-DLB5RJ7E.cjs} +16 -16
  10. package/dist/{chunk-BQPH3JDZ.cjs → chunk-FRM5XREF.cjs} +124 -21
  11. package/dist/chunk-H42U4GI5.js +49 -0
  12. package/dist/{chunk-DMGDJEUY.js → chunk-IRQX4WNQ.js} +8 -1
  13. package/dist/{chunk-ROJUYPIK.js → chunk-JV4HWHYP.js} +11 -6
  14. package/dist/{chunk-53A7IG4Y.js → chunk-KW4ZV6FJ.js} +1 -1
  15. package/dist/{chunk-7RJWFPCZ.cjs → chunk-NASWEFHN.cjs} +8 -1
  16. package/dist/chunk-OSGHCQFA.cjs +49 -0
  17. package/dist/{chunk-43LGK4YP.js → chunk-QTN5ZT4P.js} +2 -2
  18. package/dist/{chunk-TZC6RSWL.js → chunk-RTI3CLHV.js} +1 -48
  19. package/dist/{chunk-SUSDEKID.cjs → chunk-UW6W2JHW.cjs} +1 -48
  20. package/dist/{chunk-FZ6QDTC4.cjs → chunk-VIZWYFHP.cjs} +62 -11
  21. package/dist/{chunk-WY6V4Y7S.cjs → chunk-WMFHPNFP.cjs} +3 -3
  22. package/dist/{chunk-KIS7MVIW.js → chunk-Z72T6CZG.js} +61 -10
  23. package/dist/client.cjs +7 -6
  24. package/dist/client.d.cts +8 -3
  25. package/dist/client.d.ts +8 -3
  26. package/dist/client.js +6 -5
  27. package/dist/errors.cjs +4 -2
  28. package/dist/errors.d.cts +10 -1
  29. package/dist/errors.d.ts +10 -1
  30. package/dist/errors.js +3 -1
  31. package/dist/index-BPvMDXya.d.cts +101 -0
  32. package/dist/index-BPvMDXya.d.ts +101 -0
  33. package/dist/index.cjs +16 -10
  34. package/dist/index.d.cts +3 -3
  35. package/dist/index.d.ts +3 -3
  36. package/dist/index.js +15 -9
  37. package/dist/scraping.cjs +5 -4
  38. package/dist/scraping.d.cts +14 -3
  39. package/dist/scraping.d.ts +14 -3
  40. package/dist/scraping.js +4 -3
  41. package/dist/soap.cjs +4 -4
  42. package/dist/soap.d.cts +1 -1
  43. package/dist/soap.d.ts +1 -1
  44. package/dist/soap.js +3 -3
  45. package/dist/validators.cjs +4 -2
  46. package/dist/validators.d.cts +1 -1
  47. package/dist/validators.d.ts +1 -1
  48. package/dist/validators.js +5 -3
  49. package/package.json +2 -2
  50. package/dist/index-BE6Wfozd.d.cts +0 -63
  51. package/dist/index-BE6Wfozd.d.ts +0 -63
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkWY6V4Y7Scjs = require('./chunk-WY6V4Y7S.cjs');
3
+ var _chunkWMFHPNFPcjs = require('./chunk-WMFHPNFP.cjs');
4
4
 
5
5
 
6
6
 
@@ -8,7 +8,7 @@ var _chunkQH4BK5X3cjs = require('./chunk-QH4BK5X3.cjs');
8
8
 
9
9
 
10
10
 
11
- var _chunk7RJWFPCZcjs = require('./chunk-7RJWFPCZ.cjs');
11
+ var _chunkNASWEFHNcjs = require('./chunk-NASWEFHN.cjs');
12
12
 
13
13
  // src/soap/endpoints.ts
14
14
  var DGII_SOAP_BASE_URL = "https://dgii.gov.do/wsMovilDGII/WSMovilDGII.asmx";
@@ -49,13 +49,13 @@ function sanitizeJson(raw) {
49
49
  function parseContribuyenteResponse(responseXml) {
50
50
  const raw = extractTagContent(responseXml, "GetContribuyentesResult");
51
51
  if (raw === void 0) {
52
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
52
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
53
53
  "Respuesta SOAP sin GetContribuyentesResult"
54
54
  );
55
55
  }
56
56
  const trimmed = raw.trim();
57
57
  if (trimmed === "0" || trimmed === "") {
58
- throw new (0, _chunk7RJWFPCZcjs.DgiiNotFoundError)(
58
+ throw new (0, _chunkNASWEFHNcjs.DgiiNotFoundError)(
59
59
  "RNC o c\xE9dula no encontrado en el registro de la DGII"
60
60
  );
61
61
  }
@@ -65,12 +65,12 @@ function parseContribuyenteResponse(responseXml) {
65
65
  try {
66
66
  parsed = JSON.parse(sanitized);
67
67
  } catch (e) {
68
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
68
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
69
69
  "Respuesta de la DGII no es JSON v\xE1lido"
70
70
  );
71
71
  }
72
72
  if (typeof parsed !== "object" || parsed === null || typeof parsed["RGE_RUC"] !== "string") {
73
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
73
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
74
74
  "Formato de respuesta de la DGII inesperado"
75
75
  );
76
76
  }
@@ -88,7 +88,7 @@ function parseContribuyenteResponse(responseXml) {
88
88
  function parseNcfResponse(responseXml) {
89
89
  const raw = extractTagContent(responseXml, "GetNCFResult");
90
90
  if (raw === void 0) {
91
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("Respuesta SOAP sin GetNCFResult");
91
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("Respuesta SOAP sin GetNCFResult");
92
92
  }
93
93
  const trimmed = raw.trim();
94
94
  if (trimmed === "0" || trimmed === "") {
@@ -99,12 +99,12 @@ function parseNcfResponse(responseXml) {
99
99
  try {
100
100
  parsed = JSON.parse(sanitized);
101
101
  } catch (e2) {
102
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
102
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
103
103
  "Respuesta de la DGII no es JSON v\xE1lido"
104
104
  );
105
105
  }
106
106
  if (typeof parsed !== "object" || parsed === null) {
107
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
107
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
108
108
  "Formato de respuesta de la DGII inesperado"
109
109
  );
110
110
  }
@@ -144,22 +144,22 @@ var DgiiSoapClient = class {
144
144
  signal: AbortSignal.timeout(timeout)
145
145
  });
146
146
  } catch (error) {
147
- throw _chunkWY6V4Y7Scjs.wrapFetchError.call(void 0, error, timeout);
147
+ throw _chunkWMFHPNFPcjs.wrapFetchError.call(void 0, error, timeout);
148
148
  }
149
149
  const contentLength = response.headers.get("content-length");
150
150
  if (contentLength && parseInt(contentLength, 10) > 1048576) {
151
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
151
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
152
152
  "Respuesta de la DGII excede el tama\xF1o m\xE1ximo permitido"
153
153
  );
154
154
  }
155
155
  if (response.status === 403) {
156
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
156
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
157
157
  "Acceso denegado por la DGII (HTTP 403). El servicio puede estar restringido por ubicaci\xF3n geogr\xE1fica.",
158
158
  { statusCode: 403 }
159
159
  );
160
160
  }
161
161
  if (!response.ok) {
162
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
162
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
163
163
  `El servicio de la DGII respondi\xF3 con HTTP ${response.status}`,
164
164
  { statusCode: response.status }
165
165
  );
@@ -171,7 +171,7 @@ var DgiiSoapClient = class {
171
171
  */
172
172
  async getContribuyente(rnc) {
173
173
  if (typeof rnc !== "string" || rnc.trim() === "") {
174
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
174
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
175
175
  }
176
176
  const envelope = buildGetContribuyentesEnvelope(rnc.trim());
177
177
  const responseXml = await this._fetch(
@@ -185,10 +185,10 @@ var DgiiSoapClient = class {
185
185
  */
186
186
  async getNCF(rnc, ncf) {
187
187
  if (typeof rnc !== "string" || rnc.trim() === "") {
188
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
188
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
189
189
  }
190
190
  if (typeof ncf !== "string" || ncf.trim() === "") {
191
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("El par\xE1metro ncf es requerido");
191
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("El par\xE1metro ncf es requerido");
192
192
  }
193
193
  const envelope = buildGetNcfEnvelope(rnc.trim(), ncf.trim());
194
194
  const responseXml = await this._fetch(SOAP_ACTIONS.getNCF, envelope);
@@ -1,6 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkWY6V4Y7Scjs = require('./chunk-WY6V4Y7S.cjs');
3
+ var _chunkOSGHCQFAcjs = require('./chunk-OSGHCQFA.cjs');
4
+
5
+
6
+ var _chunkWMFHPNFPcjs = require('./chunk-WMFHPNFP.cjs');
4
7
 
5
8
 
6
9
 
@@ -8,7 +11,7 @@ var _chunkQH4BK5X3cjs = require('./chunk-QH4BK5X3.cjs');
8
11
 
9
12
 
10
13
 
11
- var _chunk7RJWFPCZcjs = require('./chunk-7RJWFPCZ.cjs');
14
+ var _chunkNASWEFHNcjs = require('./chunk-NASWEFHN.cjs');
12
15
 
13
16
  // src/scraping/endpoints.ts
14
17
  var DGII_RNC_URL = "https://dgii.gov.do/app/WebApps/ConsultasWeb2/ConsultasWeb/consultas/rnc.aspx";
@@ -21,16 +24,30 @@ var FORM_FIELDS = /* @__PURE__ */ Object.freeze({
21
24
  rncSubmit: "ctl00$cphMain$btnBuscarPorRNC",
22
25
  ncfRncInput: "ctl00$cphMain$txtRNC",
23
26
  ncfInput: "ctl00$cphMain$txtNCF",
24
- ncfSubmit: "ctl00$cphMain$btnConsultar"
27
+ ncfSubmit: "ctl00$cphMain$btnConsultar",
28
+ // Campos adicionales para e-NCF (serie E)
29
+ ncfRncCompradorInput: "ctl00$cphMain$txtRncComprador",
30
+ ncfCodigoSeguridadInput: "ctl00$cphMain$txtCodigoSeg"
25
31
  });
26
32
 
27
33
  // src/scraping/html-parser.ts
34
+ var NCF_INVALID_PHRASES = /* @__PURE__ */ Object.freeze([
35
+ "no es v",
36
+ "no se encuentra",
37
+ "no existe",
38
+ // Respuesta de la DGII a un e-NCF con código de seguridad incorrecto
39
+ "no encontrado"
40
+ ]);
41
+ function isKnownInvalidMessage(message) {
42
+ const normalized = message.toLowerCase();
43
+ return NCF_INVALID_PHRASES.some((phrase) => normalized.includes(phrase));
44
+ }
28
45
  function extractViewStateTokens(html) {
29
46
  const viewState = extractInputValue(html, "__VIEWSTATE");
30
47
  const viewStateGenerator = extractInputValue(html, "__VIEWSTATEGENERATOR");
31
48
  const eventValidation = extractInputValue(html, "__EVENTVALIDATION");
32
49
  if (!viewState || !eventValidation) {
33
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
50
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
34
51
  "No se encontraron tokens ViewState en la p\xE1gina de la DGII"
35
52
  );
36
53
  }
@@ -43,7 +60,7 @@ function parseContribuyenteHtml(html) {
43
60
  if (infoEnd !== -1) {
44
61
  const infoBlock = html.slice(infoStart, infoEnd);
45
62
  if (infoBlock.includes("no se encuentra")) {
46
- throw new (0, _chunk7RJWFPCZcjs.DgiiNotFoundError)(
63
+ throw new (0, _chunkNASWEFHNcjs.DgiiNotFoundError)(
47
64
  "RNC o c\xE9dula no encontrado en el registro de la DGII"
48
65
  );
49
66
  }
@@ -52,13 +69,13 @@ function parseContribuyenteHtml(html) {
52
69
  const tableId = "cphMain_dvDatosContribuyentes";
53
70
  const tableStart = html.indexOf(tableId);
54
71
  if (tableStart === -1) {
55
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
72
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
56
73
  "Formato de respuesta HTML inesperado: tabla de resultados no encontrada"
57
74
  );
58
75
  }
59
76
  const tableEnd = html.indexOf("</table>", tableStart);
60
77
  if (tableEnd === -1) {
61
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
78
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
62
79
  "Formato de respuesta HTML inesperado: tabla incompleta"
63
80
  );
64
81
  }
@@ -91,7 +108,7 @@ function parseNcfHtml(html) {
91
108
  const infoEnd = html.indexOf("</span>", infoStart);
92
109
  if (infoEnd !== -1) {
93
110
  const infoBlock = html.slice(infoStart, infoEnd);
94
- if (infoBlock.includes("no es v") || infoBlock.includes("no se encuentra") || infoBlock.includes("no existe")) {
111
+ if (isKnownInvalidMessage(infoBlock)) {
95
112
  return { valid: false, rnc: "", ncf: "", nombreComercial: void 0 };
96
113
  }
97
114
  }
@@ -121,6 +138,58 @@ function parseNcfHtml(html) {
121
138
  nombreComercial: nombreComercial ? _chunkQH4BK5X3cjs.collapseSpaces.call(void 0, nombreComercial) : void 0
122
139
  };
123
140
  }
141
+ function parseEcfHtml(html) {
142
+ const info = extractSpanValue(html, "cphMain_lblInformacion");
143
+ if (info && isKnownInvalidMessage(info)) {
144
+ return { valid: false, rnc: "", ncf: "" };
145
+ }
146
+ if (info) {
147
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(`La DGII respondi\xF3: ${info}`);
148
+ }
149
+ if (!html.includes("cphMain_PResultadoFE")) {
150
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
151
+ "Formato de respuesta HTML inesperado: panel de resultado e-NCF no encontrado"
152
+ );
153
+ }
154
+ const rncEmisor = extractSpanValue(html, "cphMain_lblrncemisor");
155
+ const ncf = extractSpanValue(html, "cphMain_lblencf");
156
+ if (!rncEmisor && !ncf) {
157
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
158
+ "Formato de respuesta HTML inesperado: panel e-NCF sin emisor ni e-NCF"
159
+ );
160
+ }
161
+ const rncComprador = extractSpanValue(html, "cphMain_lblrnccomprador");
162
+ const codigoSeguridad = extractSpanValue(html, "cphMain_lblCodSeguridad");
163
+ const estado = extractSpanValue(html, "cphMain_lblEstadoFe");
164
+ const fechaEmision = extractSpanValue(html, "cphMain_lblFechaEmision");
165
+ const fechaFirma = extractSpanValue(html, "cphMain_lblFechaFirma");
166
+ return {
167
+ valid: true,
168
+ rnc: _chunkQH4BK5X3cjs.stripNonDigits.call(void 0, rncEmisor),
169
+ ncf: _chunkQH4BK5X3cjs.collapseSpaces.call(void 0, ncf),
170
+ rncComprador: rncComprador ? _chunkQH4BK5X3cjs.stripNonDigits.call(void 0, rncComprador) : void 0,
171
+ codigoSeguridad: codigoSeguridad || void 0,
172
+ estado: estado || void 0,
173
+ montoTotal: parseAmount(extractSpanValue(html, "cphMain_lblMontoTotal")),
174
+ totalItbis: parseAmount(extractSpanValue(html, "cphMain_lblTotalItbis")),
175
+ fechaEmision: fechaEmision || void 0,
176
+ fechaFirma: fechaFirma || void 0
177
+ };
178
+ }
179
+ function parseAmount(raw) {
180
+ if (!raw) return void 0;
181
+ const value = Number(raw.replace(/,/g, ""));
182
+ return Number.isFinite(value) ? value : void 0;
183
+ }
184
+ function extractSpanValue(html, spanId) {
185
+ const idx = html.indexOf(`id="${spanId}"`);
186
+ if (idx === -1) return "";
187
+ const tagEnd = html.indexOf(">", idx);
188
+ if (tagEnd === -1) return "";
189
+ const closeTag = html.indexOf("</span>", tagEnd);
190
+ if (closeTag === -1) return "";
191
+ return decodeHtmlEntities(stripHtmlTags(html.slice(tagEnd + 1, closeTag)));
192
+ }
124
193
  function extractInputValue(html, name) {
125
194
  let idx = html.indexOf(`id="${name}"`);
126
195
  if (idx === -1) {
@@ -183,7 +252,7 @@ var ScrapingClient = class {
183
252
  */
184
253
  async getContribuyente(rnc) {
185
254
  if (typeof rnc !== "string" || rnc.trim() === "") {
186
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
255
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
187
256
  }
188
257
  const tokens = await this._fetchTokens(this._rncUrl);
189
258
  const body = buildFormBody([
@@ -201,26 +270,60 @@ var ScrapingClient = class {
201
270
  return parseContribuyenteHtml(html);
202
271
  }
203
272
  /**
204
- * Valida un comprobante fiscal (NCF) contra la DGII.
273
+ * Valida un comprobante fiscal contra la DGII.
274
+ *
275
+ * Soporta NCF (serie B) y e-NCF (serie E). Para un e-NCF la DGII
276
+ * exige el RNC del comprador; sin él responde con un mensaje de campo
277
+ * requerido y este método lanza `DgiiServiceError`.
278
+ *
279
+ * @param rnc - RNC del emisor
280
+ * @param ncf - NCF o e-NCF a validar
281
+ * @param options - Datos adicionales del e-NCF (`rncComprador`,
282
+ * `codigoSeguridad`). Se ignoran cuando `ncf` no es un e-NCF válido.
205
283
  */
206
- async getNCF(rnc, ncf) {
284
+ async getNCF(rnc, ncf, options) {
207
285
  if (typeof rnc !== "string" || rnc.trim() === "") {
208
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
286
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("El par\xE1metro rnc es requerido");
209
287
  }
210
288
  if (typeof ncf !== "string" || ncf.trim() === "") {
211
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)("El par\xE1metro ncf es requerido");
289
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)("El par\xE1metro ncf es requerido");
290
+ }
291
+ const rncComprador = _optionalChain([options, 'optionalAccess', _6 => _6.rncComprador]);
292
+ if (rncComprador !== void 0 && (typeof rncComprador !== "string" || rncComprador.trim() === "")) {
293
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
294
+ "La opci\xF3n rncComprador debe ser un string no vac\xEDo"
295
+ );
212
296
  }
297
+ const codigoSeguridad = _optionalChain([options, 'optionalAccess', _7 => _7.codigoSeguridad]);
298
+ if (codigoSeguridad !== void 0 && (typeof codigoSeguridad !== "string" || codigoSeguridad.trim() === "")) {
299
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
300
+ "La opci\xF3n codigoSeguridad debe ser un string no vac\xEDo"
301
+ );
302
+ }
303
+ const isEcf = _chunkOSGHCQFAcjs.validateEcf.call(void 0, ncf).valid;
213
304
  const tokens = await this._fetchTokens(this._ncfUrl);
214
- const body = buildFormBody([
305
+ const fields = [
215
306
  [FORM_FIELDS.viewState, tokens.viewState],
216
307
  [FORM_FIELDS.viewStateGenerator, tokens.viewStateGenerator],
217
308
  [FORM_FIELDS.eventValidation, tokens.eventValidation],
218
309
  [FORM_FIELDS.ncfRncInput, rnc.trim()],
219
- [FORM_FIELDS.ncfInput, ncf.trim()],
220
- [FORM_FIELDS.ncfSubmit, "Buscar"]
221
- ]);
310
+ [FORM_FIELDS.ncfInput, ncf.trim()]
311
+ ];
312
+ if (isEcf) {
313
+ if (rncComprador !== void 0) {
314
+ fields.push([FORM_FIELDS.ncfRncCompradorInput, rncComprador.trim()]);
315
+ }
316
+ if (codigoSeguridad !== void 0) {
317
+ fields.push([
318
+ FORM_FIELDS.ncfCodigoSeguridadInput,
319
+ codigoSeguridad.trim()
320
+ ]);
321
+ }
322
+ }
323
+ fields.push([FORM_FIELDS.ncfSubmit, "Buscar"]);
324
+ const body = buildFormBody(fields);
222
325
  const html = await this._post(this._ncfUrl, body);
223
- return parseNcfHtml(html);
326
+ return isEcf ? parseEcfHtml(html) : parseNcfHtml(html);
224
327
  }
225
328
  async _fetchTokens(url) {
226
329
  let response;
@@ -233,7 +336,7 @@ var ScrapingClient = class {
233
336
  throw this._wrapFetchError(error);
234
337
  }
235
338
  if (!response.ok) {
236
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
339
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
237
340
  `La DGII respondi\xF3 con HTTP ${response.status} al obtener la p\xE1gina`,
238
341
  { statusCode: response.status }
239
342
  );
@@ -258,7 +361,7 @@ var ScrapingClient = class {
258
361
  throw this._wrapFetchError(error);
259
362
  }
260
363
  if (!response.ok) {
261
- throw new (0, _chunk7RJWFPCZcjs.DgiiServiceError)(
364
+ throw new (0, _chunkNASWEFHNcjs.DgiiServiceError)(
262
365
  `La DGII respondi\xF3 con HTTP ${response.status}`,
263
366
  { statusCode: response.status }
264
367
  );
@@ -266,7 +369,7 @@ var ScrapingClient = class {
266
369
  return response.text();
267
370
  }
268
371
  _wrapFetchError(error) {
269
- return _chunkWY6V4Y7Scjs.wrapFetchError.call(void 0, error, this._timeout);
372
+ return _chunkWMFHPNFPcjs.wrapFetchError.call(void 0, error, this._timeout);
270
373
  }
271
374
  };
272
375
  function buildFormBody(fields) {
@@ -0,0 +1,49 @@
1
+ // src/validators/ecf.ts
2
+ var ECF_TYPES = /* @__PURE__ */ Object.freeze({
3
+ "31": "CREDITO_FISCAL_ELECTRONICA",
4
+ "32": "CONSUMO_ELECTRONICA",
5
+ "33": "NOTA_DE_DEBITO_ELECTRONICA",
6
+ "34": "NOTA_DE_CREDITO_ELECTRONICA",
7
+ "41": "COMPRAS_ELECTRONICO",
8
+ "43": "GASTOS_MENORES_ELECTRONICO",
9
+ "44": "REGIMENES_ESPECIALES_ELECTRONICO",
10
+ "45": "GUBERNAMENTAL_ELECTRONICO",
11
+ "46": "EXPORTACIONES_ELECTRONICO",
12
+ "47": "PAGOS_AL_EXTERIOR_ELECTRONICO"
13
+ });
14
+ var ECF_TYPE_NAMES = /* @__PURE__ */ Object.freeze({
15
+ "31": "Factura de cr\xE9dito fiscal electr\xF3nica",
16
+ "32": "Factura de consumo electr\xF3nica",
17
+ "33": "Nota de d\xE9bito electr\xF3nica",
18
+ "34": "Nota de cr\xE9dito electr\xF3nica",
19
+ "41": "Comprobante electr\xF3nico de compras",
20
+ "43": "Comprobante electr\xF3nico para gastos menores",
21
+ "44": "Comprobante electr\xF3nico para reg\xEDmenes especiales",
22
+ "45": "Comprobante electr\xF3nico gubernamental",
23
+ "46": "Comprobante electr\xF3nico para exportaciones",
24
+ "47": "Comprobante electr\xF3nico para pagos al exterior"
25
+ });
26
+ var ECF_PATTERN = /^E(\d{2})(\d{10})$/;
27
+ function validateEcf(value) {
28
+ if (typeof value !== "string") return { valid: false };
29
+ const normalized = value.toUpperCase().trim();
30
+ const match = ECF_PATTERN.exec(normalized);
31
+ if (!match) {
32
+ return { valid: false };
33
+ }
34
+ const typeCode = match[1];
35
+ const type = ECF_TYPES[typeCode];
36
+ if (!type) {
37
+ return { valid: false };
38
+ }
39
+ return {
40
+ valid: true,
41
+ type,
42
+ serie: `E${typeCode}`
43
+ };
44
+ }
45
+
46
+ export {
47
+ ECF_TYPE_NAMES,
48
+ validateEcf
49
+ };
@@ -34,11 +34,18 @@ var AllStrategiesFailedError = class extends DgiiError {
34
34
  this.errors = errors;
35
35
  }
36
36
  };
37
+ var BulkFormatError = class extends DgiiError {
38
+ constructor(message) {
39
+ super(message, "DGII_BULK_FORMAT_ERROR");
40
+ this.name = "BulkFormatError";
41
+ }
42
+ };
37
43
 
38
44
  export {
39
45
  DgiiError,
40
46
  DgiiConnectionError,
41
47
  DgiiNotFoundError,
42
48
  DgiiServiceError,
43
- AllStrategiesFailedError
49
+ AllStrategiesFailedError,
50
+ BulkFormatError
44
51
  };
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  DgiiSoapClient
3
- } from "./chunk-43LGK4YP.js";
3
+ } from "./chunk-QTN5ZT4P.js";
4
4
  import {
5
5
  ScrapingClient
6
- } from "./chunk-HRRYZUKI.js";
6
+ } from "./chunk-7ILLRYE4.js";
7
7
  import {
8
8
  AllStrategiesFailedError,
9
9
  DgiiConnectionError,
10
10
  DgiiNotFoundError,
11
11
  DgiiServiceError
12
- } from "./chunk-DMGDJEUY.js";
12
+ } from "./chunk-IRQX4WNQ.js";
13
13
 
14
14
  // src/client/circuit-breaker.ts
15
15
  var DEFAULT_CIRCUIT_BREAKER_OPTIONS = /* @__PURE__ */ Object.freeze({
@@ -150,11 +150,16 @@ var DgiiClient = class {
150
150
  );
151
151
  }
152
152
  /**
153
- * Valida un comprobante fiscal (NCF) contra la DGII.
153
+ * Valida un comprobante fiscal contra la DGII.
154
+ *
155
+ * @param rnc - RNC del emisor
156
+ * @param ncf - NCF o e-NCF a validar
157
+ * @param options - Datos adicionales del e-NCF (`rncComprador`,
158
+ * `codigoSeguridad`). Se ignoran cuando `ncf` no es un e-NCF válido.
154
159
  */
155
- async getNCF(rnc, ncf) {
160
+ async getNCF(rnc, ncf, options) {
156
161
  return this._executeWithFallback(
157
- (client) => client.getNCF(rnc, ncf)
162
+ (client) => client.getNCF(rnc, ncf, options)
158
163
  );
159
164
  }
160
165
  async _executeWithFallback(operation) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DgiiConnectionError
3
- } from "./chunk-DMGDJEUY.js";
3
+ } from "./chunk-IRQX4WNQ.js";
4
4
 
5
5
  // src/utils/fetch-error.ts
6
6
  function wrapFetchError(error, timeoutMs) {
@@ -34,6 +34,13 @@ var AllStrategiesFailedError = class extends DgiiError {
34
34
  this.errors = errors;
35
35
  }
36
36
  };
37
+ var BulkFormatError = class extends DgiiError {
38
+ constructor(message) {
39
+ super(message, "DGII_BULK_FORMAT_ERROR");
40
+ this.name = "BulkFormatError";
41
+ }
42
+ };
43
+
37
44
 
38
45
 
39
46
 
@@ -41,4 +48,4 @@ var AllStrategiesFailedError = class extends DgiiError {
41
48
 
42
49
 
43
50
 
44
- exports.DgiiError = DgiiError; exports.DgiiConnectionError = DgiiConnectionError; exports.DgiiNotFoundError = DgiiNotFoundError; exports.DgiiServiceError = DgiiServiceError; exports.AllStrategiesFailedError = AllStrategiesFailedError;
51
+ exports.DgiiError = DgiiError; exports.DgiiConnectionError = DgiiConnectionError; exports.DgiiNotFoundError = DgiiNotFoundError; exports.DgiiServiceError = DgiiServiceError; exports.AllStrategiesFailedError = AllStrategiesFailedError; exports.BulkFormatError = BulkFormatError;
@@ -0,0 +1,49 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/validators/ecf.ts
2
+ var ECF_TYPES = /* @__PURE__ */ Object.freeze({
3
+ "31": "CREDITO_FISCAL_ELECTRONICA",
4
+ "32": "CONSUMO_ELECTRONICA",
5
+ "33": "NOTA_DE_DEBITO_ELECTRONICA",
6
+ "34": "NOTA_DE_CREDITO_ELECTRONICA",
7
+ "41": "COMPRAS_ELECTRONICO",
8
+ "43": "GASTOS_MENORES_ELECTRONICO",
9
+ "44": "REGIMENES_ESPECIALES_ELECTRONICO",
10
+ "45": "GUBERNAMENTAL_ELECTRONICO",
11
+ "46": "EXPORTACIONES_ELECTRONICO",
12
+ "47": "PAGOS_AL_EXTERIOR_ELECTRONICO"
13
+ });
14
+ var ECF_TYPE_NAMES = /* @__PURE__ */ Object.freeze({
15
+ "31": "Factura de cr\xE9dito fiscal electr\xF3nica",
16
+ "32": "Factura de consumo electr\xF3nica",
17
+ "33": "Nota de d\xE9bito electr\xF3nica",
18
+ "34": "Nota de cr\xE9dito electr\xF3nica",
19
+ "41": "Comprobante electr\xF3nico de compras",
20
+ "43": "Comprobante electr\xF3nico para gastos menores",
21
+ "44": "Comprobante electr\xF3nico para reg\xEDmenes especiales",
22
+ "45": "Comprobante electr\xF3nico gubernamental",
23
+ "46": "Comprobante electr\xF3nico para exportaciones",
24
+ "47": "Comprobante electr\xF3nico para pagos al exterior"
25
+ });
26
+ var ECF_PATTERN = /^E(\d{2})(\d{10})$/;
27
+ function validateEcf(value) {
28
+ if (typeof value !== "string") return { valid: false };
29
+ const normalized = value.toUpperCase().trim();
30
+ const match = ECF_PATTERN.exec(normalized);
31
+ if (!match) {
32
+ return { valid: false };
33
+ }
34
+ const typeCode = match[1];
35
+ const type = ECF_TYPES[typeCode];
36
+ if (!type) {
37
+ return { valid: false };
38
+ }
39
+ return {
40
+ valid: true,
41
+ type,
42
+ serie: `E${typeCode}`
43
+ };
44
+ }
45
+
46
+
47
+
48
+
49
+ exports.ECF_TYPE_NAMES = ECF_TYPE_NAMES; exports.validateEcf = validateEcf;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  wrapFetchError
3
- } from "./chunk-53A7IG4Y.js";
3
+ } from "./chunk-KW4ZV6FJ.js";
4
4
  import {
5
5
  collapseSpaces,
6
6
  stripNonDigits
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  DgiiNotFoundError,
10
10
  DgiiServiceError
11
- } from "./chunk-DMGDJEUY.js";
11
+ } from "./chunk-IRQX4WNQ.js";
12
12
 
13
13
  // src/soap/endpoints.ts
14
14
  var DGII_SOAP_BASE_URL = "https://dgii.gov.do/wsMovilDGII/WSMovilDGII.asmx";
@@ -729,56 +729,9 @@ function validateNcf(value) {
729
729
  };
730
730
  }
731
731
 
732
- // src/validators/ecf.ts
733
- var ECF_TYPES = /* @__PURE__ */ Object.freeze({
734
- "31": "CREDITO_FISCAL_ELECTRONICA",
735
- "32": "CONSUMO_ELECTRONICA",
736
- "33": "NOTA_DE_DEBITO_ELECTRONICA",
737
- "34": "NOTA_DE_CREDITO_ELECTRONICA",
738
- "41": "COMPRAS_ELECTRONICO",
739
- "43": "GASTOS_MENORES_ELECTRONICO",
740
- "44": "REGIMENES_ESPECIALES_ELECTRONICO",
741
- "45": "GUBERNAMENTAL_ELECTRONICO",
742
- "46": "EXPORTACIONES_ELECTRONICO",
743
- "47": "PAGOS_AL_EXTERIOR_ELECTRONICO"
744
- });
745
- var ECF_TYPE_NAMES = /* @__PURE__ */ Object.freeze({
746
- "31": "Factura de cr\xE9dito fiscal electr\xF3nica",
747
- "32": "Factura de consumo electr\xF3nica",
748
- "33": "Nota de d\xE9bito electr\xF3nica",
749
- "34": "Nota de cr\xE9dito electr\xF3nica",
750
- "41": "Comprobante electr\xF3nico de compras",
751
- "43": "Comprobante electr\xF3nico para gastos menores",
752
- "44": "Comprobante electr\xF3nico para reg\xEDmenes especiales",
753
- "45": "Comprobante electr\xF3nico gubernamental",
754
- "46": "Comprobante electr\xF3nico para exportaciones",
755
- "47": "Comprobante electr\xF3nico para pagos al exterior"
756
- });
757
- var ECF_PATTERN = /^E(\d{2})(\d{10})$/;
758
- function validateEcf(value) {
759
- if (typeof value !== "string") return { valid: false };
760
- const normalized = value.toUpperCase().trim();
761
- const match = ECF_PATTERN.exec(normalized);
762
- if (!match) {
763
- return { valid: false };
764
- }
765
- const typeCode = match[1];
766
- const type = ECF_TYPES[typeCode];
767
- if (!type) {
768
- return { valid: false };
769
- }
770
- return {
771
- valid: true,
772
- type,
773
- serie: `E${typeCode}`
774
- };
775
- }
776
-
777
732
  export {
778
733
  validateRnc,
779
734
  validateCedula,
780
735
  NCF_TYPE_NAMES,
781
- validateNcf,
782
- ECF_TYPE_NAMES,
783
- validateEcf
736
+ validateNcf
784
737
  };