@deuriib/dgii-ecf 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +212 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -3
- package/dist/index.d.ts +92 -3
- package/dist/index.js +208 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,8 +31,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
BaseUrl: () => BaseUrl,
|
|
34
|
+
CONSUMPTION_SUMMARY_THRESHOLD: () => CONSUMPTION_SUMMARY_THRESHOLD,
|
|
34
35
|
DgiiError: () => DgiiError,
|
|
35
36
|
ECF: () => ECF,
|
|
37
|
+
ECF_TYPE_CODES: () => ECF_TYPE_CODES,
|
|
36
38
|
Endpoint: () => Endpoint,
|
|
37
39
|
Environment: () => Environment,
|
|
38
40
|
Err: () => import_neverthrow.Err,
|
|
@@ -47,6 +49,7 @@ __export(index_exports, {
|
|
|
47
49
|
Transformer: () => Transformer,
|
|
48
50
|
buildSenderReceiverUrl: () => buildSenderReceiverUrl,
|
|
49
51
|
buildUrl: () => buildUrl,
|
|
52
|
+
compareDecimal: () => compareDecimal,
|
|
50
53
|
convertECF32ToRFCE: () => convertECF32ToRFCE,
|
|
51
54
|
createResiliencePolicies: () => createResiliencePolicies,
|
|
52
55
|
defaultResilienceOptions: () => defaultResilienceOptions,
|
|
@@ -62,10 +65,12 @@ __export(index_exports, {
|
|
|
62
65
|
getCurrentFormattedDate: () => getCurrentFormattedDate,
|
|
63
66
|
getCurrentFormattedDateTime: () => getCurrentFormattedDateTime,
|
|
64
67
|
getXmlFromBodyResponse: () => getXmlFromBodyResponse,
|
|
68
|
+
isEcfTypeCode: () => isEcfTypeCode,
|
|
65
69
|
isRetryableError: () => isRetryableError,
|
|
66
70
|
isRetryableStatus: () => isRetryableStatus,
|
|
67
71
|
ok: () => import_neverthrow.ok,
|
|
68
72
|
okAsync: () => import_neverthrow.okAsync,
|
|
73
|
+
resolveReceptionRoute: () => resolveReceptionRoute,
|
|
69
74
|
roundHalfUpToCents: () => roundHalfUpToCents,
|
|
70
75
|
toDgiiError: () => toDgiiError,
|
|
71
76
|
validateXMLCertificate: () => validateXMLCertificate
|
|
@@ -422,9 +427,13 @@ var HttpClient = class {
|
|
|
422
427
|
policies;
|
|
423
428
|
fetchImpl;
|
|
424
429
|
baseUrl;
|
|
430
|
+
beforeRequest;
|
|
431
|
+
onUnauthorized;
|
|
425
432
|
constructor(options) {
|
|
426
433
|
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
427
434
|
this.token = options.token;
|
|
435
|
+
this.beforeRequest = options.beforeRequest;
|
|
436
|
+
this.onUnauthorized = options.onUnauthorized;
|
|
428
437
|
this.policies = options.policies ?? createResiliencePolicies({
|
|
429
438
|
...options.resilience,
|
|
430
439
|
...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {}
|
|
@@ -434,6 +443,9 @@ var HttpClient = class {
|
|
|
434
443
|
setToken(token) {
|
|
435
444
|
this.token = token;
|
|
436
445
|
}
|
|
446
|
+
getToken() {
|
|
447
|
+
return this.token;
|
|
448
|
+
}
|
|
437
449
|
clearToken() {
|
|
438
450
|
this.token = void 0;
|
|
439
451
|
}
|
|
@@ -493,6 +505,19 @@ var HttpClient = class {
|
|
|
493
505
|
return (0, import_neverthrow.err)(error);
|
|
494
506
|
}
|
|
495
507
|
async request(options) {
|
|
508
|
+
if (!options.skipAuthHooks) {
|
|
509
|
+
await this.beforeRequest?.();
|
|
510
|
+
}
|
|
511
|
+
const first = await this.execute(options);
|
|
512
|
+
if (!options.skipAuthHooks && first.isErr() && first.error.status === 401 && this.onUnauthorized !== void 0) {
|
|
513
|
+
const replayed = await this.onUnauthorized();
|
|
514
|
+
if (replayed) {
|
|
515
|
+
return this.execute(options);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return first;
|
|
519
|
+
}
|
|
520
|
+
async execute(options) {
|
|
496
521
|
const url = this.buildUrl(options.path, options.absoluteUrl, options.query);
|
|
497
522
|
const method = options.method ?? "GET";
|
|
498
523
|
const headers = this.authHeaders(options.headers);
|
|
@@ -521,7 +546,8 @@ var HttpClient = class {
|
|
|
521
546
|
path,
|
|
522
547
|
query,
|
|
523
548
|
absoluteUrl: opts?.absoluteUrl,
|
|
524
|
-
resource: opts?.resource
|
|
549
|
+
resource: opts?.resource,
|
|
550
|
+
skipAuthHooks: opts?.skipAuthHooks
|
|
525
551
|
});
|
|
526
552
|
}
|
|
527
553
|
/**
|
|
@@ -537,7 +563,8 @@ var HttpClient = class {
|
|
|
537
563
|
body: form,
|
|
538
564
|
headers: { Accept: "application/json" },
|
|
539
565
|
absoluteUrl: opts?.absoluteUrl,
|
|
540
|
-
resource: opts?.resource
|
|
566
|
+
resource: opts?.resource,
|
|
567
|
+
skipAuthHooks: opts?.skipAuthHooks
|
|
541
568
|
});
|
|
542
569
|
}
|
|
543
570
|
};
|
|
@@ -668,22 +695,6 @@ var C14N_INCLUSIVE = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
|
|
|
668
695
|
var RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
|
|
669
696
|
var SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256";
|
|
670
697
|
var ENVELOPED = "http://www.w3.org/2000/09/xmldsig#enveloped-signature";
|
|
671
|
-
var CUSTOM_DIGEST_URI = "http://dgii.gov.do/digest/sha256-c14n";
|
|
672
|
-
var DgiiDigest = class {
|
|
673
|
-
getHash(xml) {
|
|
674
|
-
const doc = new import_xmldom.DOMParser().parseFromString(
|
|
675
|
-
xml
|
|
676
|
-
);
|
|
677
|
-
const canonical = new import_xml_crypto.C14nCanonicalization().process(
|
|
678
|
-
doc,
|
|
679
|
-
{}
|
|
680
|
-
);
|
|
681
|
-
return import_node_crypto.default.createHash("sha256").update(canonical, "utf8").digest("base64");
|
|
682
|
-
}
|
|
683
|
-
getAlgorithmName() {
|
|
684
|
-
return SHA256;
|
|
685
|
-
}
|
|
686
|
-
};
|
|
687
698
|
var parseStrict = (xml) => {
|
|
688
699
|
const errors = [];
|
|
689
700
|
const doc = new import_xmldom.DOMParser({
|
|
@@ -752,12 +763,10 @@ var Signature = class {
|
|
|
752
763
|
signatureAlgorithm: RSA_SHA256,
|
|
753
764
|
canonicalizationAlgorithm: C14N_INCLUSIVE
|
|
754
765
|
});
|
|
755
|
-
const hashAlgorithms = sig.HashAlgorithms;
|
|
756
|
-
hashAlgorithms[CUSTOM_DIGEST_URI] = DgiiDigest;
|
|
757
766
|
sig.addReference({
|
|
758
767
|
xpath: `//*[local-name(.)='${elementName}']`,
|
|
759
768
|
transforms: [ENVELOPED],
|
|
760
|
-
digestAlgorithm:
|
|
769
|
+
digestAlgorithm: SHA256,
|
|
761
770
|
isEmptyUri: true
|
|
762
771
|
});
|
|
763
772
|
cleanNodes(doc);
|
|
@@ -903,6 +912,98 @@ var extractElementText = (xml, tag) => {
|
|
|
903
912
|
const text = match?.[1]?.trim();
|
|
904
913
|
return text === void 0 || text === "" ? void 0 : text;
|
|
905
914
|
};
|
|
915
|
+
var ROOT_PATTERN = /<\s*(?:[A-Za-z_][\w.-]*:)?([A-Za-z_][\w.-]*)[\s/>]/;
|
|
916
|
+
var extractRootElementName = (xml) => {
|
|
917
|
+
const stripped = xml.replace(/<\?[\s\S]*?\?>/g, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
|
|
918
|
+
return ROOT_PATTERN.exec(stripped)?.[1];
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
// src/reception.ts
|
|
922
|
+
var ECF_TYPE_CODES = [
|
|
923
|
+
"31",
|
|
924
|
+
"32",
|
|
925
|
+
"33",
|
|
926
|
+
"34",
|
|
927
|
+
"41",
|
|
928
|
+
"43",
|
|
929
|
+
"44",
|
|
930
|
+
"45",
|
|
931
|
+
"46",
|
|
932
|
+
"47"
|
|
933
|
+
];
|
|
934
|
+
var CONSUMPTION_SUMMARY_THRESHOLD = "250000";
|
|
935
|
+
var CONSUMPTION_TYPE = "32";
|
|
936
|
+
var GENERAL = {
|
|
937
|
+
kind: "general",
|
|
938
|
+
endpoint: "recepcion/api/FacturasElectronicas" /* SendInvoice */
|
|
939
|
+
};
|
|
940
|
+
var SUMMARY = {
|
|
941
|
+
kind: "summary",
|
|
942
|
+
endpoint: "recepcionfc/api/recepcion/ecf" /* SendSummary */
|
|
943
|
+
};
|
|
944
|
+
var isEcfTypeCode = (value) => ECF_TYPE_CODES.includes(value);
|
|
945
|
+
var DECIMAL_PATTERN = /^\d+(?:\.\d+)?$/;
|
|
946
|
+
var compareDecimal = (a, b) => {
|
|
947
|
+
const [aInt = "", aFrac = ""] = a.split(".");
|
|
948
|
+
const [bInt = "", bFrac = ""] = b.split(".");
|
|
949
|
+
const aWhole = aInt.replace(/^0+(?=\d)/, "");
|
|
950
|
+
const bWhole = bInt.replace(/^0+(?=\d)/, "");
|
|
951
|
+
if (aWhole.length !== bWhole.length) {
|
|
952
|
+
return aWhole.length - bWhole.length;
|
|
953
|
+
}
|
|
954
|
+
if (aWhole !== bWhole) {
|
|
955
|
+
return aWhole < bWhole ? -1 : 1;
|
|
956
|
+
}
|
|
957
|
+
const width = Math.max(aFrac.length, bFrac.length);
|
|
958
|
+
const aPadded = aFrac.padEnd(width, "0");
|
|
959
|
+
const bPadded = bFrac.padEnd(width, "0");
|
|
960
|
+
if (aPadded === bPadded) {
|
|
961
|
+
return 0;
|
|
962
|
+
}
|
|
963
|
+
return aPadded < bPadded ? -1 : 1;
|
|
964
|
+
};
|
|
965
|
+
var validationError = (message) => new DgiiError(message, { code: "VALIDATION" });
|
|
966
|
+
var resolveReceptionRoute = (signedXml) => {
|
|
967
|
+
const root = extractRootElementName(signedXml);
|
|
968
|
+
if (root === "RFCE") {
|
|
969
|
+
return (0, import_neverthrow.ok)(SUMMARY);
|
|
970
|
+
}
|
|
971
|
+
if (root !== "ECF") {
|
|
972
|
+
return (0, import_neverthrow.err)(
|
|
973
|
+
validationError(
|
|
974
|
+
`Unsupported document root "${root ?? "unknown"}"; expected "ECF" or "RFCE"`
|
|
975
|
+
)
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
const tipo = extractElementText(signedXml, "TipoeCF");
|
|
979
|
+
if (tipo === void 0) {
|
|
980
|
+
return (0, import_neverthrow.err)(validationError("TipoeCF is missing from the document"));
|
|
981
|
+
}
|
|
982
|
+
if (!isEcfTypeCode(tipo)) {
|
|
983
|
+
return (0, import_neverthrow.err)(validationError(`Unknown TipoeCF "${tipo}"`));
|
|
984
|
+
}
|
|
985
|
+
if (tipo !== CONSUMPTION_TYPE) {
|
|
986
|
+
return (0, import_neverthrow.ok)(GENERAL);
|
|
987
|
+
}
|
|
988
|
+
const total = extractElementText(signedXml, "MontoTotal");
|
|
989
|
+
if (total === void 0) {
|
|
990
|
+
return (0, import_neverthrow.err)(
|
|
991
|
+
validationError(
|
|
992
|
+
"MontoTotal is required to route an E32 consumption invoice"
|
|
993
|
+
)
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
if (!DECIMAL_PATTERN.test(total)) {
|
|
997
|
+
return (0, import_neverthrow.err)(
|
|
998
|
+
validationError(`MontoTotal "${total}" is not a decimal amount`)
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
return compareDecimal(total, CONSUMPTION_SUMMARY_THRESHOLD) < 0 ? (0, import_neverthrow.err)(
|
|
1002
|
+
validationError(
|
|
1003
|
+
"An E32 below RD$250,000 must be sent as an RFCE summary; convert it with convertECF32ToRFCE first"
|
|
1004
|
+
)
|
|
1005
|
+
) : (0, import_neverthrow.ok)(GENERAL);
|
|
1006
|
+
};
|
|
906
1007
|
|
|
907
1008
|
// src/utils.ts
|
|
908
1009
|
var getCodeSixDigitfromSignature = (signedXml) => {
|
|
@@ -1066,22 +1167,39 @@ var import_node_crypto2 = require("crypto");
|
|
|
1066
1167
|
var PENDING_SUBMISSION = { pending: true };
|
|
1067
1168
|
var isPendingSubmission = (value) => typeof value === "object" && value !== null && value.pending === true;
|
|
1068
1169
|
var sha256Hex = (value) => (0, import_node_crypto2.createHash)("sha256").update(value, "utf8").digest("hex");
|
|
1170
|
+
var parseExpiry = (value) => {
|
|
1171
|
+
if (value === void 0) {
|
|
1172
|
+
return void 0;
|
|
1173
|
+
}
|
|
1174
|
+
const parsed = Date.parse(value);
|
|
1175
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
1176
|
+
};
|
|
1069
1177
|
var ECF = class {
|
|
1070
1178
|
environment;
|
|
1071
1179
|
http;
|
|
1072
1180
|
idempotency;
|
|
1073
1181
|
credentials;
|
|
1074
1182
|
inFlight = /* @__PURE__ */ new Map();
|
|
1183
|
+
tokenRefreshSkewMs;
|
|
1184
|
+
now;
|
|
1185
|
+
tokenExpiresAt;
|
|
1186
|
+
refreshPromise;
|
|
1075
1187
|
constructor(credentials, environment = "TesteCF" /* Dev */, options = {}) {
|
|
1076
1188
|
this.credentials = credentials;
|
|
1077
1189
|
this.environment = environment;
|
|
1190
|
+
this.tokenRefreshSkewMs = options.tokenRefreshSkewMs ?? 5 * 60 * 1e3;
|
|
1191
|
+
this.now = options.now ?? Date.now;
|
|
1078
1192
|
this.idempotency = options.idempotencyStore ?? new InMemoryIdempotencyStore();
|
|
1079
1193
|
this.http = new HttpClient({
|
|
1080
1194
|
baseUrl: BaseUrl.ECF,
|
|
1081
1195
|
...options.token !== void 0 ? { token: options.token } : {},
|
|
1082
1196
|
...options.resilience !== void 0 ? { resilience: options.resilience } : {},
|
|
1083
1197
|
...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
|
|
1084
|
-
...options.fetchImpl !== void 0 ? { fetchImpl: options.fetchImpl } : {}
|
|
1198
|
+
...options.fetchImpl !== void 0 ? { fetchImpl: options.fetchImpl } : {},
|
|
1199
|
+
beforeRequest: async () => {
|
|
1200
|
+
await this.ensureToken();
|
|
1201
|
+
},
|
|
1202
|
+
onUnauthorized: () => this.reauthenticate()
|
|
1085
1203
|
});
|
|
1086
1204
|
}
|
|
1087
1205
|
buildIdempotencyKey(signedXml) {
|
|
@@ -1133,6 +1251,40 @@ var ECF = class {
|
|
|
1133
1251
|
this.inFlight.delete(key);
|
|
1134
1252
|
}
|
|
1135
1253
|
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Refresh the token when it is missing or about to expire.
|
|
1256
|
+
*
|
|
1257
|
+
* A pre-supplied `token` has no known expiry, so it is never refreshed
|
|
1258
|
+
* proactively — only a 401 triggers a re-authentication for it.
|
|
1259
|
+
*/
|
|
1260
|
+
async ensureToken() {
|
|
1261
|
+
if (this.tokenExpiresAt === void 0) {
|
|
1262
|
+
return (0, import_neverthrow.ok)(void 0);
|
|
1263
|
+
}
|
|
1264
|
+
if (this.now() < this.tokenExpiresAt - this.tokenRefreshSkewMs) {
|
|
1265
|
+
return (0, import_neverthrow.ok)(void 0);
|
|
1266
|
+
}
|
|
1267
|
+
const refreshed = await this.refreshToken();
|
|
1268
|
+
return refreshed.isOk() ? (0, import_neverthrow.ok)(void 0) : (0, import_neverthrow.err)(refreshed.error);
|
|
1269
|
+
}
|
|
1270
|
+
/** Authenticate, coalescing concurrent refreshes into a single round-trip. */
|
|
1271
|
+
refreshToken() {
|
|
1272
|
+
if (this.refreshPromise !== void 0) {
|
|
1273
|
+
return this.refreshPromise;
|
|
1274
|
+
}
|
|
1275
|
+
const promise = this.authenticate().finally(() => {
|
|
1276
|
+
this.refreshPromise = void 0;
|
|
1277
|
+
});
|
|
1278
|
+
this.refreshPromise = promise;
|
|
1279
|
+
return promise;
|
|
1280
|
+
}
|
|
1281
|
+
/** Drop the rejected token and authenticate once. Returns `true` on success. */
|
|
1282
|
+
async reauthenticate() {
|
|
1283
|
+
this.http.clearToken();
|
|
1284
|
+
this.tokenExpiresAt = void 0;
|
|
1285
|
+
const refreshed = await this.refreshToken();
|
|
1286
|
+
return refreshed.isOk();
|
|
1287
|
+
}
|
|
1136
1288
|
/** Authenticate against DGII (or a buyer host) and store the bearer token. */
|
|
1137
1289
|
async authenticate(buyerHost) {
|
|
1138
1290
|
const seed = await this.getSeed(buyerHost);
|
|
@@ -1159,6 +1311,7 @@ var ECF = class {
|
|
|
1159
1311
|
return (0, import_neverthrow.err)(token.error);
|
|
1160
1312
|
}
|
|
1161
1313
|
this.http.setToken(token.value.token);
|
|
1314
|
+
this.tokenExpiresAt = parseExpiry(token.value.expira);
|
|
1162
1315
|
return (0, import_neverthrow.ok)(token.value);
|
|
1163
1316
|
}
|
|
1164
1317
|
getSeed(buyerHost) {
|
|
@@ -1169,20 +1322,23 @@ var ECF = class {
|
|
|
1169
1322
|
);
|
|
1170
1323
|
return this.http.get(url2, void 0, {
|
|
1171
1324
|
absoluteUrl: true,
|
|
1172
|
-
resource: "fe/autenticacion/api/semilla" /* Seed
|
|
1325
|
+
resource: "fe/autenticacion/api/semilla" /* Seed */,
|
|
1326
|
+
skipAuthHooks: true
|
|
1173
1327
|
});
|
|
1174
1328
|
}
|
|
1175
1329
|
const url = buildUrl(this.environment, "Autenticacion/api/Autenticacion/Semilla" /* Seed */);
|
|
1176
1330
|
return this.http.get(url, void 0, {
|
|
1177
1331
|
absoluteUrl: true,
|
|
1178
|
-
resource: "Autenticacion/api/Autenticacion/Semilla" /* Seed
|
|
1332
|
+
resource: "Autenticacion/api/Autenticacion/Semilla" /* Seed */,
|
|
1333
|
+
skipAuthHooks: true
|
|
1179
1334
|
});
|
|
1180
1335
|
}
|
|
1181
1336
|
getAuthToken(signedSeed, buyerHost) {
|
|
1182
1337
|
const url = buyerHost ? buildSenderReceiverUrl(buyerHost, "fe/autenticacion/api/validacioncertificado" /* ValidateSeed */) : buildUrl(this.environment, "autenticacion/api/Autenticacion/ValidarSemilla" /* ValidateSeed */);
|
|
1183
1338
|
return this.http.postMultipart(url, "signed.xml", signedSeed, {
|
|
1184
1339
|
absoluteUrl: true,
|
|
1185
|
-
resource: "autenticacion/api/Autenticacion/ValidarSemilla" /* ValidateSeed
|
|
1340
|
+
resource: "autenticacion/api/Autenticacion/ValidarSemilla" /* ValidateSeed */,
|
|
1341
|
+
skipAuthHooks: true
|
|
1186
1342
|
});
|
|
1187
1343
|
}
|
|
1188
1344
|
/**
|
|
@@ -1214,6 +1370,32 @@ var ECF = class {
|
|
|
1214
1370
|
)
|
|
1215
1371
|
);
|
|
1216
1372
|
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Submit a signed document to the endpoint its own content belongs to.
|
|
1375
|
+
*
|
|
1376
|
+
* Reads the root element, `TipoeCF` and `MontoTotal` from the signed XML and
|
|
1377
|
+
* dispatches to {@link sendSummary} for an RFCE or to
|
|
1378
|
+
* {@link sendElectronicDocument} for an ECF. An E32 below RD$250,000 is
|
|
1379
|
+
* rejected because DGII only accepts the summary form for those.
|
|
1380
|
+
*/
|
|
1381
|
+
async sendDocument(signedXml, fileName, buyerHost) {
|
|
1382
|
+
const route = resolveReceptionRoute(signedXml);
|
|
1383
|
+
if (route.isErr()) {
|
|
1384
|
+
return (0, import_neverthrow.err)(route.error);
|
|
1385
|
+
}
|
|
1386
|
+
if (route.value.kind === "summary") {
|
|
1387
|
+
if (buyerHost !== void 0) {
|
|
1388
|
+
return (0, import_neverthrow.err)(
|
|
1389
|
+
new DgiiError(
|
|
1390
|
+
"An RFCE summary cannot be delivered directly to a buyer host",
|
|
1391
|
+
{ code: "VALIDATION" }
|
|
1392
|
+
)
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
return this.sendSummary(signedXml, fileName);
|
|
1396
|
+
}
|
|
1397
|
+
return this.sendElectronicDocument(signedXml, fileName, buyerHost);
|
|
1398
|
+
}
|
|
1217
1399
|
statusTrackId(trackId) {
|
|
1218
1400
|
const url = buildUrl(this.environment, "consultaresultado/api/Consultas/Estado" /* TrackResultStatus */);
|
|
1219
1401
|
return this.http.get(
|
|
@@ -1308,8 +1490,10 @@ var ECF = class {
|
|
|
1308
1490
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1309
1491
|
0 && (module.exports = {
|
|
1310
1492
|
BaseUrl,
|
|
1493
|
+
CONSUMPTION_SUMMARY_THRESHOLD,
|
|
1311
1494
|
DgiiError,
|
|
1312
1495
|
ECF,
|
|
1496
|
+
ECF_TYPE_CODES,
|
|
1313
1497
|
Endpoint,
|
|
1314
1498
|
Environment,
|
|
1315
1499
|
Err,
|
|
@@ -1324,6 +1508,7 @@ var ECF = class {
|
|
|
1324
1508
|
Transformer,
|
|
1325
1509
|
buildSenderReceiverUrl,
|
|
1326
1510
|
buildUrl,
|
|
1511
|
+
compareDecimal,
|
|
1327
1512
|
convertECF32ToRFCE,
|
|
1328
1513
|
createResiliencePolicies,
|
|
1329
1514
|
defaultResilienceOptions,
|
|
@@ -1339,10 +1524,12 @@ var ECF = class {
|
|
|
1339
1524
|
getCurrentFormattedDate,
|
|
1340
1525
|
getCurrentFormattedDateTime,
|
|
1341
1526
|
getXmlFromBodyResponse,
|
|
1527
|
+
isEcfTypeCode,
|
|
1342
1528
|
isRetryableError,
|
|
1343
1529
|
isRetryableStatus,
|
|
1344
1530
|
ok,
|
|
1345
1531
|
okAsync,
|
|
1532
|
+
resolveReceptionRoute,
|
|
1346
1533
|
roundHalfUpToCents,
|
|
1347
1534
|
toDgiiError,
|
|
1348
1535
|
validateXMLCertificate
|