@ar-agents/mercadopago 0.8.0 → 0.9.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/CHANGELOG.md +78 -0
- package/README.md +99 -1
- package/dist/index.cjs +298 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +251 -2
- package/dist/index.d.ts +251 -2
- package/dist/index.js +297 -23
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
- package/tools.manifest.json +1 -1
package/dist/index.js
CHANGED
|
@@ -164,6 +164,8 @@ var MercadoPagoClient = class {
|
|
|
164
164
|
requestTimeoutMs;
|
|
165
165
|
maxRetries;
|
|
166
166
|
onCall;
|
|
167
|
+
circuitBreaker;
|
|
168
|
+
traceContext;
|
|
167
169
|
constructor(options) {
|
|
168
170
|
if (!options.accessToken) {
|
|
169
171
|
throw new Error(
|
|
@@ -176,8 +178,24 @@ var MercadoPagoClient = class {
|
|
|
176
178
|
this.requestTimeoutMs = options.requestTimeoutMs ?? 3e4;
|
|
177
179
|
this.maxRetries = Math.max(0, options.maxRetries ?? 1);
|
|
178
180
|
this.onCall = options.onCall;
|
|
181
|
+
this.circuitBreaker = options.circuitBreaker;
|
|
182
|
+
this.traceContext = options.traceContext;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* v0.9 — Inspect the circuit breaker state (when configured). Returns
|
|
186
|
+
* `null` when no circuit breaker is wired. Useful for health checks.
|
|
187
|
+
*/
|
|
188
|
+
getCircuitState() {
|
|
189
|
+
return this.circuitBreaker?.getStats() ?? null;
|
|
179
190
|
}
|
|
180
191
|
async request(method, path, body, options) {
|
|
192
|
+
const exec = () => this.requestUnprotected(method, path, body, options);
|
|
193
|
+
if (this.circuitBreaker) {
|
|
194
|
+
return this.circuitBreaker.execute(exec);
|
|
195
|
+
}
|
|
196
|
+
return exec();
|
|
197
|
+
}
|
|
198
|
+
async requestUnprotected(method, path, body, options) {
|
|
181
199
|
const headers = {
|
|
182
200
|
Authorization: `Bearer ${this.accessToken}`,
|
|
183
201
|
"Content-Type": "application/json"
|
|
@@ -185,6 +203,11 @@ var MercadoPagoClient = class {
|
|
|
185
203
|
if (options?.idempotencyKey) {
|
|
186
204
|
headers["X-Idempotency-Key"] = options.idempotencyKey;
|
|
187
205
|
}
|
|
206
|
+
const trace = this.traceContext?.();
|
|
207
|
+
if (trace?.traceId && trace?.spanId) {
|
|
208
|
+
const flags = (trace.traceFlags ?? 1).toString(16).padStart(2, "0");
|
|
209
|
+
headers["traceparent"] = `00-${trace.traceId}-${trace.spanId}-${flags}`;
|
|
210
|
+
}
|
|
188
211
|
let url = `${this.baseUrl}${path}`;
|
|
189
212
|
if (options?.query) {
|
|
190
213
|
const search = new URLSearchParams();
|
|
@@ -201,24 +224,54 @@ var MercadoPagoClient = class {
|
|
|
201
224
|
let attempt = 0;
|
|
202
225
|
let lastError;
|
|
203
226
|
let lastStatus = null;
|
|
227
|
+
const fireOnCall = (event) => {
|
|
228
|
+
const traceCtx = trace?.traceId ? {
|
|
229
|
+
traceId: trace.traceId,
|
|
230
|
+
...trace.spanId !== void 0 ? { spanId: trace.spanId } : {}
|
|
231
|
+
} : void 0;
|
|
232
|
+
this.onCall?.({
|
|
233
|
+
method,
|
|
234
|
+
path,
|
|
235
|
+
durationMs: Date.now() - t0,
|
|
236
|
+
...event,
|
|
237
|
+
...this.circuitBreaker ? { circuitState: this.circuitBreaker.getState() } : {},
|
|
238
|
+
...traceCtx ? { traceContext: traceCtx } : {}
|
|
239
|
+
});
|
|
240
|
+
};
|
|
204
241
|
while (attempt <= this.maxRetries) {
|
|
205
242
|
const controller = new AbortController();
|
|
206
243
|
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
244
|
+
const parentSignal = options?.signal;
|
|
245
|
+
const onParentAbort = () => controller.abort();
|
|
246
|
+
if (parentSignal) {
|
|
247
|
+
if (parentSignal.aborted) {
|
|
248
|
+
clearTimeout(timer);
|
|
249
|
+
throw new MercadoPagoTimeoutError(path, 0);
|
|
250
|
+
}
|
|
251
|
+
parentSignal.addEventListener("abort", onParentAbort, { once: true });
|
|
252
|
+
}
|
|
207
253
|
const init = { method, headers, signal: controller.signal };
|
|
208
254
|
if (body !== void 0) init.body = JSON.stringify(body);
|
|
209
255
|
try {
|
|
210
256
|
const res = await fetchFn(url, init);
|
|
211
257
|
clearTimeout(timer);
|
|
258
|
+
if (parentSignal) parentSignal.removeEventListener("abort", onParentAbort);
|
|
212
259
|
lastStatus = res.status;
|
|
260
|
+
const requestId = res.headers.get("x-request-id");
|
|
261
|
+
const rlRemaining = res.headers.get("x-rate-limit-remaining");
|
|
262
|
+
const rlReset = res.headers.get("x-rate-limit-reset");
|
|
263
|
+
const rateLimit = {
|
|
264
|
+
remaining: rlRemaining !== null ? Number(rlRemaining) : null,
|
|
265
|
+
resetSeconds: rlReset !== null ? Number(rlReset) : null
|
|
266
|
+
};
|
|
213
267
|
if (res.ok) {
|
|
214
268
|
const text2 = await res.text();
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
path,
|
|
218
|
-
durationMs: Date.now() - t0,
|
|
269
|
+
fireOnCall({
|
|
270
|
+
success: true,
|
|
219
271
|
httpStatus: res.status,
|
|
220
272
|
retried: attempt,
|
|
221
|
-
|
|
273
|
+
requestId,
|
|
274
|
+
rateLimit
|
|
222
275
|
});
|
|
223
276
|
if (!text2) return void 0;
|
|
224
277
|
return JSON.parse(text2);
|
|
@@ -233,13 +286,12 @@ var MercadoPagoClient = class {
|
|
|
233
286
|
}
|
|
234
287
|
const contentType = res.headers.get("content-type") ?? "";
|
|
235
288
|
if (res.status >= 500 && !contentType.includes("application/json")) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
path,
|
|
239
|
-
durationMs: Date.now() - t0,
|
|
289
|
+
fireOnCall({
|
|
290
|
+
success: false,
|
|
240
291
|
httpStatus: res.status,
|
|
241
292
|
retried: attempt,
|
|
242
|
-
|
|
293
|
+
requestId,
|
|
294
|
+
rateLimit
|
|
243
295
|
});
|
|
244
296
|
throw new MercadoPagoOverloadedError(path, res.status);
|
|
245
297
|
}
|
|
@@ -251,33 +303,33 @@ var MercadoPagoClient = class {
|
|
|
251
303
|
parsed = text;
|
|
252
304
|
}
|
|
253
305
|
const err = classifyError(res.status, path, parsed, options?.classifyContext);
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
path,
|
|
257
|
-
durationMs: Date.now() - t0,
|
|
306
|
+
fireOnCall({
|
|
307
|
+
success: false,
|
|
258
308
|
httpStatus: res.status,
|
|
259
309
|
retried: attempt,
|
|
260
|
-
|
|
310
|
+
requestId,
|
|
311
|
+
rateLimit
|
|
261
312
|
});
|
|
262
313
|
throw err;
|
|
263
314
|
} catch (err) {
|
|
264
315
|
clearTimeout(timer);
|
|
316
|
+
if (parentSignal) parentSignal.removeEventListener("abort", onParentAbort);
|
|
265
317
|
if (err instanceof MercadoPagoError) throw err;
|
|
266
318
|
const isAbort = err instanceof Error && err.name === "AbortError";
|
|
319
|
+
const isParentAbort = parentSignal?.aborted ?? false;
|
|
267
320
|
const isNetwork = !lastStatus && !isAbort;
|
|
268
|
-
if ((isNetwork || isAbort) && attempt < this.maxRetries) {
|
|
321
|
+
if ((isNetwork || isAbort && !isParentAbort) && attempt < this.maxRetries) {
|
|
269
322
|
lastError = err;
|
|
270
323
|
attempt++;
|
|
271
324
|
await sleep(250 * Math.pow(2, attempt - 1));
|
|
272
325
|
continue;
|
|
273
326
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
path,
|
|
277
|
-
durationMs: Date.now() - t0,
|
|
327
|
+
fireOnCall({
|
|
328
|
+
success: false,
|
|
278
329
|
httpStatus: lastStatus,
|
|
279
330
|
retried: attempt,
|
|
280
|
-
|
|
331
|
+
requestId: null,
|
|
332
|
+
rateLimit: { remaining: null, resetSeconds: null }
|
|
281
333
|
});
|
|
282
334
|
if (isAbort) {
|
|
283
335
|
throw new MercadoPagoTimeoutError(path, this.requestTimeoutMs);
|
|
@@ -1231,6 +1283,53 @@ var MercadoPagoClient = class {
|
|
|
1231
1283
|
);
|
|
1232
1284
|
return { id: intentId, canceled: true };
|
|
1233
1285
|
}
|
|
1286
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1287
|
+
// v0.9 — Health check
|
|
1288
|
+
//
|
|
1289
|
+
// No dedicated ping endpoint exists in MP's public API. We use `getMe()`
|
|
1290
|
+
// (`/users/me`) as a lightweight liveness probe — it requires only a valid
|
|
1291
|
+
// accessToken, returns ~200 bytes of JSON, and is the same call MP's own
|
|
1292
|
+
// dashboard makes on startup. A successful response proves: (a) network
|
|
1293
|
+
// path to MP is up, (b) accessToken is valid, (c) MP is responding.
|
|
1294
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1295
|
+
/**
|
|
1296
|
+
* Liveness probe against MP. Returns latency + circuit-breaker state.
|
|
1297
|
+
* Use as a /health endpoint for k8s, Vercel cron, or status-page checks.
|
|
1298
|
+
*
|
|
1299
|
+
* Returns `{ ok: false, ... }` instead of throwing — designed for
|
|
1300
|
+
* monitoring loops that want to keep running.
|
|
1301
|
+
*
|
|
1302
|
+
* @param signal Optional AbortSignal to cap wait time (e.g., 2s for
|
|
1303
|
+
* status-page polling).
|
|
1304
|
+
*/
|
|
1305
|
+
async healthCheck(signal) {
|
|
1306
|
+
const t0 = Date.now();
|
|
1307
|
+
const circuitBefore = this.circuitBreaker?.getStats() ?? null;
|
|
1308
|
+
try {
|
|
1309
|
+
const me = await this.request(
|
|
1310
|
+
"GET",
|
|
1311
|
+
"/users/me",
|
|
1312
|
+
void 0,
|
|
1313
|
+
signal ? { signal } : {}
|
|
1314
|
+
);
|
|
1315
|
+
return {
|
|
1316
|
+
ok: true,
|
|
1317
|
+
latencyMs: Date.now() - t0,
|
|
1318
|
+
userId: String(me.id),
|
|
1319
|
+
error: null,
|
|
1320
|
+
circuit: this.circuitBreaker?.getStats() ?? null
|
|
1321
|
+
};
|
|
1322
|
+
} catch (err) {
|
|
1323
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1324
|
+
return {
|
|
1325
|
+
ok: false,
|
|
1326
|
+
latencyMs: Date.now() - t0,
|
|
1327
|
+
userId: null,
|
|
1328
|
+
error: message,
|
|
1329
|
+
circuit: this.circuitBreaker?.getStats() ?? circuitBefore
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1234
1333
|
};
|
|
1235
1334
|
|
|
1236
1335
|
// src/crypto.ts
|
|
@@ -2298,7 +2397,9 @@ var DEFAULT_DESCRIPTIONS = {
|
|
|
2298
2397
|
cancel_point_payment_intent: "Cancel an OPEN point payment intent before the buyer interacts with the device. ONLY WORKS while state='OPEN' \u2014 once the buyer taps, you can't cancel; refund_payment after the fact instead.",
|
|
2299
2398
|
// ── Pure helpers (v0.7) ──────────────────────────────────────────────────
|
|
2300
2399
|
compute_marketplace_fee: "PURE HELPER (no network) \u2014 given a transaction amount + fee rule (% or flat ARS, with optional min/max floors), returns the exact `marketplace_fee` value in ARS to pass to create_order or create_payment_preference. USE WHEN your platform takes a commission and you need to compute the exact fee per transaction. Examples: { percent: 5, minArs: 50, maxArs: 5000 } for percentage with floor + cap; { flatArs: 200, percent: 2 } for fixed + percentage.",
|
|
2301
|
-
explain_payment_status: "PURE HELPER (no network) \u2014 given a Payment object (from get_payment / create_payment / handle_webhook), returns { summary, recommendedAction, final, paid, retryable } in Spanish. Translates MP's cryptic status_detail codes to plain Spanish + actionable guidance ('reintentar con otra tarjeta' vs 'esperar webhook' vs 'estado final'). USE THIS instead of having to memorize 30+ status_detail codes \u2014 surface summary + recommendedAction directly to the user."
|
|
2400
|
+
explain_payment_status: "PURE HELPER (no network) \u2014 given a Payment object (from get_payment / create_payment / handle_webhook), returns { summary, recommendedAction, final, paid, retryable } in Spanish. Translates MP's cryptic status_detail codes to plain Spanish + actionable guidance ('reintentar con otra tarjeta' vs 'esperar webhook' vs 'estado final'). USE THIS instead of having to memorize 30+ status_detail codes \u2014 surface summary + recommendedAction directly to the user.",
|
|
2401
|
+
// ── v0.9 — Health check + observability ──────────────────────────────────
|
|
2402
|
+
mp_health_check: "Liveness probe against MP. Returns { ok, latencyMs, userId, circuit }. USE THIS as the first call in long-running agent workflows to verify (a) network path to MP is up, (b) accessToken is valid, (c) MP is responding. Circuit-breaker state included when configured \u2014 surface to ops dashboards. Returns ok=false instead of throwing \u2014 safe to call in monitoring loops without try/catch."
|
|
2302
2403
|
};
|
|
2303
2404
|
function mercadoPagoTools(client, options) {
|
|
2304
2405
|
const desc = (name) => options.descriptions?.[name] ?? DEFAULT_DESCRIPTIONS[name];
|
|
@@ -4056,6 +4157,21 @@ function mercadoPagoTools(client, options) {
|
|
|
4056
4157
|
};
|
|
4057
4158
|
}
|
|
4058
4159
|
}),
|
|
4160
|
+
mp_health_check: tool({
|
|
4161
|
+
description: desc("mp_health_check"),
|
|
4162
|
+
inputSchema: z.object({
|
|
4163
|
+
timeout_ms: z.number().int().positive().max(3e4).optional().describe("Cap the wait time (default 5s). Use lower for status-page polling.")
|
|
4164
|
+
}),
|
|
4165
|
+
execute: async ({ timeout_ms }) => {
|
|
4166
|
+
const controller = new AbortController();
|
|
4167
|
+
const t = setTimeout(() => controller.abort(), timeout_ms ?? 5e3);
|
|
4168
|
+
try {
|
|
4169
|
+
return await client.healthCheck(controller.signal);
|
|
4170
|
+
} finally {
|
|
4171
|
+
clearTimeout(t);
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
}),
|
|
4059
4175
|
explain_payment_status: tool({
|
|
4060
4176
|
description: desc("explain_payment_status"),
|
|
4061
4177
|
inputSchema: z.object({
|
|
@@ -4146,6 +4262,164 @@ var InMemoryIdempotencyCache = class {
|
|
|
4146
4262
|
}
|
|
4147
4263
|
};
|
|
4148
4264
|
|
|
4149
|
-
|
|
4265
|
+
// src/circuit-breaker.ts
|
|
4266
|
+
var CircuitOpenError = class extends Error {
|
|
4267
|
+
constructor(retryAfterMs, consecutiveFailures) {
|
|
4268
|
+
super(
|
|
4269
|
+
`Circuit breaker is OPEN \u2014 failing fast. Retry in ${Math.ceil(
|
|
4270
|
+
retryAfterMs / 1e3
|
|
4271
|
+
)}s. Consecutive upstream failures: ${consecutiveFailures}.`
|
|
4272
|
+
);
|
|
4273
|
+
this.retryAfterMs = retryAfterMs;
|
|
4274
|
+
this.consecutiveFailures = consecutiveFailures;
|
|
4275
|
+
this.name = "CircuitOpenError";
|
|
4276
|
+
}
|
|
4277
|
+
retryAfterMs;
|
|
4278
|
+
consecutiveFailures;
|
|
4279
|
+
};
|
|
4280
|
+
var CircuitBreaker = class {
|
|
4281
|
+
state = "CLOSED";
|
|
4282
|
+
consecutiveFailures = 0;
|
|
4283
|
+
halfOpenSuccesses = 0;
|
|
4284
|
+
openedAt = 0;
|
|
4285
|
+
/** Timestamps of failures within the monitoring window. */
|
|
4286
|
+
failureWindow = [];
|
|
4287
|
+
failureThreshold;
|
|
4288
|
+
successThreshold;
|
|
4289
|
+
resetTimeoutMs;
|
|
4290
|
+
monitoringWindowMs;
|
|
4291
|
+
onStateChange;
|
|
4292
|
+
isFailureFn;
|
|
4293
|
+
now;
|
|
4294
|
+
constructor(opts = {}) {
|
|
4295
|
+
this.failureThreshold = opts.failureThreshold ?? 5;
|
|
4296
|
+
this.successThreshold = opts.successThreshold ?? 2;
|
|
4297
|
+
this.resetTimeoutMs = opts.resetTimeoutMs ?? 3e4;
|
|
4298
|
+
this.monitoringWindowMs = opts.monitoringWindowMs ?? 6e4;
|
|
4299
|
+
this.onStateChange = opts.onStateChange ?? null;
|
|
4300
|
+
this.isFailureFn = opts.isFailure ?? (() => true);
|
|
4301
|
+
this.now = opts.now ?? Date.now;
|
|
4302
|
+
}
|
|
4303
|
+
/** Read the current state. Useful for health checks + metrics. */
|
|
4304
|
+
getState() {
|
|
4305
|
+
if (this.state === "OPEN" && this.now() - this.openedAt >= this.resetTimeoutMs) {
|
|
4306
|
+
this.transitionTo("HALF_OPEN");
|
|
4307
|
+
}
|
|
4308
|
+
return this.state;
|
|
4309
|
+
}
|
|
4310
|
+
/** Read diagnostic state for health checks + dashboards. */
|
|
4311
|
+
getStats() {
|
|
4312
|
+
const state = this.getState();
|
|
4313
|
+
const msSinceOpened = this.openedAt > 0 ? this.now() - this.openedAt : null;
|
|
4314
|
+
const msUntilHalfOpen = state === "OPEN" && msSinceOpened !== null ? Math.max(0, this.resetTimeoutMs - msSinceOpened) : null;
|
|
4315
|
+
return {
|
|
4316
|
+
state,
|
|
4317
|
+
consecutiveFailures: this.consecutiveFailures,
|
|
4318
|
+
failuresInWindow: this.failuresInCurrentWindow(),
|
|
4319
|
+
msSinceOpened,
|
|
4320
|
+
msUntilHalfOpen
|
|
4321
|
+
};
|
|
4322
|
+
}
|
|
4323
|
+
/**
|
|
4324
|
+
* Execute `fn` under the breaker's protection.
|
|
4325
|
+
* - If the breaker is OPEN, throws `CircuitOpenError` immediately.
|
|
4326
|
+
* - If `fn` succeeds, may transition HALF_OPEN → CLOSED.
|
|
4327
|
+
* - If `fn` fails (and the error counts as a failure), records the
|
|
4328
|
+
* failure; may transition CLOSED → OPEN or HALF_OPEN → OPEN.
|
|
4329
|
+
*/
|
|
4330
|
+
async execute(fn) {
|
|
4331
|
+
const state = this.getState();
|
|
4332
|
+
if (state === "OPEN") {
|
|
4333
|
+
const elapsed = this.now() - this.openedAt;
|
|
4334
|
+
throw new CircuitOpenError(
|
|
4335
|
+
Math.max(0, this.resetTimeoutMs - elapsed),
|
|
4336
|
+
this.consecutiveFailures
|
|
4337
|
+
);
|
|
4338
|
+
}
|
|
4339
|
+
try {
|
|
4340
|
+
const result = await fn();
|
|
4341
|
+
this.recordSuccess();
|
|
4342
|
+
return result;
|
|
4343
|
+
} catch (err) {
|
|
4344
|
+
if (this.isFailureFn(err)) {
|
|
4345
|
+
this.recordFailure(err);
|
|
4346
|
+
}
|
|
4347
|
+
throw err;
|
|
4348
|
+
}
|
|
4349
|
+
}
|
|
4350
|
+
/** Manually force the breaker open. Useful for runbook / manual ops. */
|
|
4351
|
+
trip(reason) {
|
|
4352
|
+
if (this.state !== "OPEN") {
|
|
4353
|
+
this.transitionTo("OPEN", reason);
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4356
|
+
/** Manually reset the breaker to CLOSED. */
|
|
4357
|
+
reset() {
|
|
4358
|
+
this.consecutiveFailures = 0;
|
|
4359
|
+
this.halfOpenSuccesses = 0;
|
|
4360
|
+
this.failureWindow = [];
|
|
4361
|
+
if (this.state !== "CLOSED") {
|
|
4362
|
+
this.transitionTo("CLOSED");
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
4366
|
+
// Internal
|
|
4367
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
4368
|
+
recordSuccess() {
|
|
4369
|
+
this.consecutiveFailures = 0;
|
|
4370
|
+
if (this.state === "HALF_OPEN") {
|
|
4371
|
+
this.halfOpenSuccesses++;
|
|
4372
|
+
if (this.halfOpenSuccesses >= this.successThreshold) {
|
|
4373
|
+
this.transitionTo("CLOSED");
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
4377
|
+
recordFailure(cause) {
|
|
4378
|
+
this.consecutiveFailures++;
|
|
4379
|
+
this.failureWindow.push(this.now());
|
|
4380
|
+
this.pruneWindow();
|
|
4381
|
+
if (this.state === "HALF_OPEN") {
|
|
4382
|
+
this.transitionTo("OPEN", cause);
|
|
4383
|
+
return;
|
|
4384
|
+
}
|
|
4385
|
+
if (this.state === "CLOSED" && this.failuresInCurrentWindow() >= this.failureThreshold) {
|
|
4386
|
+
this.transitionTo("OPEN", cause);
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4389
|
+
transitionTo(to, cause) {
|
|
4390
|
+
const from = this.state;
|
|
4391
|
+
if (from === to) return;
|
|
4392
|
+
this.state = to;
|
|
4393
|
+
if (to === "OPEN") {
|
|
4394
|
+
this.openedAt = this.now();
|
|
4395
|
+
this.halfOpenSuccesses = 0;
|
|
4396
|
+
} else if (to === "CLOSED") {
|
|
4397
|
+
this.consecutiveFailures = 0;
|
|
4398
|
+
this.halfOpenSuccesses = 0;
|
|
4399
|
+
this.failureWindow = [];
|
|
4400
|
+
this.openedAt = 0;
|
|
4401
|
+
} else if (to === "HALF_OPEN") {
|
|
4402
|
+
this.halfOpenSuccesses = 0;
|
|
4403
|
+
}
|
|
4404
|
+
this.onStateChange?.({
|
|
4405
|
+
from,
|
|
4406
|
+
to,
|
|
4407
|
+
cause,
|
|
4408
|
+
consecutiveFailures: this.consecutiveFailures
|
|
4409
|
+
});
|
|
4410
|
+
}
|
|
4411
|
+
pruneWindow() {
|
|
4412
|
+
const cutoff = this.now() - this.monitoringWindowMs;
|
|
4413
|
+
while (this.failureWindow.length > 0 && this.failureWindow[0] < cutoff) {
|
|
4414
|
+
this.failureWindow.shift();
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
failuresInCurrentWindow() {
|
|
4418
|
+
this.pruneWindow();
|
|
4419
|
+
return this.failureWindow.length;
|
|
4420
|
+
}
|
|
4421
|
+
};
|
|
4422
|
+
|
|
4423
|
+
export { CircuitBreaker, CircuitOpenError, InMemoryIdempotencyCache, InMemoryOAuthTokenStore, InMemoryStateAdapter, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, TEST_CARDS_AR, TEST_PAYERS_AR, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
|
|
4150
4424
|
//# sourceMappingURL=index.js.map
|
|
4151
4425
|
//# sourceMappingURL=index.js.map
|