@ar-agents/mercadopago 0.16.0 → 0.17.1

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.
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Recipe 15 — Prorated subscription pause/resume.
3
+ *
4
+ * MP's pause API freezes recurring charges but doesn't auto-prorate the
5
+ * unused period the customer already paid for. If you offer a "pause your
6
+ * subscription, resume next month" feature, you need to:
7
+ *
8
+ * 1. Compute how many days are left in the current billing period.
9
+ * 2. Refund a prorated amount for those unused days (or store as credit).
10
+ * 3. Pause the subscription on MP.
11
+ * 4. On resume, adjust the next-billing date so the customer doesn't
12
+ * double-pay for the period they were paused.
13
+ *
14
+ * # Why this matters
15
+ *
16
+ * Without proration, customers who pause feel ripped off ("I paid for a
17
+ * month and you only gave me 10 days"). With proration but no resume
18
+ * adjustment, you bill them again immediately on resume. Both kill retention.
19
+ *
20
+ * # The math
21
+ *
22
+ * billingPeriodStart ─────────────► billingPeriodEnd
23
+ * │ pausedAt
24
+ * └─ daysUnused = (end - pausedAt) / 86400000
25
+ * prorated = monthlyAmount * (daysUnused / daysInPeriod)
26
+ *
27
+ * On resume, the next charge happens after `daysUnused` from now (instead
28
+ * of the original schedule).
29
+ */
30
+
31
+ import {
32
+ MercadoPagoClient,
33
+ type Preapproval,
34
+ } from "@ar-agents/mercadopago";
35
+
36
+ const mp = new MercadoPagoClient({
37
+ accessToken: process.env.MP_ACCESS_TOKEN!,
38
+ });
39
+
40
+ // ─────────────────────────────────────────────────────────────────────────────
41
+ // State for tracking pause history
42
+ // ─────────────────────────────────────────────────────────────────────────────
43
+
44
+ type PauseRecord = {
45
+ subscriptionId: string;
46
+ pausedAt: number; // unix ms
47
+ unusedDays: number;
48
+ proratedRefund: number;
49
+ refundId: string | null;
50
+ };
51
+
52
+ const pauseStore = new Map<string, PauseRecord>();
53
+
54
+ // ─────────────────────────────────────────────────────────────────────────────
55
+ // Pause with proration
56
+ // ─────────────────────────────────────────────────────────────────────────────
57
+
58
+ export async function pauseSubscriptionWithProration(args: {
59
+ subscriptionId: string;
60
+ /** When pause is requested. Defaults to now. */
61
+ pausedAt?: Date;
62
+ /**
63
+ * If true, refund the unused-period amount to the customer's payment
64
+ * method. If false, store the credit and apply on resume.
65
+ */
66
+ refundUnused: boolean;
67
+ }): Promise<{
68
+ unusedDays: number;
69
+ proratedAmount: number;
70
+ refundId: string | null;
71
+ }> {
72
+ const pausedAtMs = (args.pausedAt ?? new Date()).getTime();
73
+ const sub = await mp.getPreapproval(args.subscriptionId);
74
+
75
+ // Find the most recent successful charge to know when the current period
76
+ // started, and the next_payment_date to know when it would have ended.
77
+ const billingPeriodStart = sub.last_modified
78
+ ? new Date(sub.last_modified).getTime()
79
+ : pausedAtMs - 30 * 86_400_000; // fallback: 30 days ago
80
+
81
+ // MP doesn't always populate `next_payment_date` — derive from the
82
+ // recurrence config when missing.
83
+ const billingPeriodEnd = computePeriodEnd(sub, billingPeriodStart);
84
+
85
+ const totalDays = (billingPeriodEnd - billingPeriodStart) / 86_400_000;
86
+ const usedDays = (pausedAtMs - billingPeriodStart) / 86_400_000;
87
+ const unusedDays = Math.max(0, totalDays - usedDays);
88
+
89
+ const monthlyAmount = sub.auto_recurring?.transaction_amount ?? 0;
90
+ const proratedAmount = Math.round(
91
+ (monthlyAmount * unusedDays) / Math.max(totalDays, 1),
92
+ );
93
+
94
+ let refundId: string | null = null;
95
+ if (args.refundUnused && proratedAmount > 0) {
96
+ // Find the most recent charge under this subscription to refund against.
97
+ const recent = await mp.listSubscriptionPayments(args.subscriptionId, {
98
+ limit: 5,
99
+ });
100
+ const lastApproved = recent.results.find((p) => p.status === "approved");
101
+ if (lastApproved?.payment_id) {
102
+ const refund = await mp.createRefund({
103
+ payment_id: String(lastApproved.payment_id),
104
+ amount: proratedAmount,
105
+ });
106
+ refundId = String(refund.id);
107
+ }
108
+ }
109
+
110
+ // Now actually pause MP-side.
111
+ await mp.pausePreapproval(args.subscriptionId);
112
+
113
+ pauseStore.set(args.subscriptionId, {
114
+ subscriptionId: args.subscriptionId,
115
+ pausedAt: pausedAtMs,
116
+ unusedDays,
117
+ proratedRefund: proratedAmount,
118
+ refundId,
119
+ });
120
+
121
+ return { unusedDays, proratedAmount, refundId };
122
+ }
123
+
124
+ // ─────────────────────────────────────────────────────────────────────────────
125
+ // Resume with adjusted next-billing date
126
+ // ─────────────────────────────────────────────────────────────────────────────
127
+
128
+ export async function resumeSubscriptionWithAdjustment(
129
+ subscriptionId: string,
130
+ ): Promise<{
131
+ resumedAt: Date;
132
+ nextBillingDate: Date;
133
+ creditAppliedFromPause: number;
134
+ }> {
135
+ const record = pauseStore.get(subscriptionId);
136
+ if (!record) {
137
+ // No pause record — just resume normally; MP picks up its own schedule.
138
+ await mp.resumePreapproval(subscriptionId);
139
+ return {
140
+ resumedAt: new Date(),
141
+ nextBillingDate: new Date(Date.now() + 30 * 86_400_000), // approximate
142
+ creditAppliedFromPause: 0,
143
+ };
144
+ }
145
+
146
+ // Resume the subscription. MP's resume sets the next charge to "tomorrow"
147
+ // by default; we want to delay by the unused-days credit.
148
+ await mp.resumePreapproval(subscriptionId);
149
+
150
+ const resumedAt = new Date();
151
+ const adjustedNextBilling = new Date(
152
+ resumedAt.getTime() + record.unusedDays * 86_400_000,
153
+ );
154
+
155
+ // MP doesn't expose a way to push the next charge date directly via the
156
+ // public API. The pragmatic workaround: cancel the subscription's first
157
+ // post-resume charge from your webhook handler when it fires, having
158
+ // already credited the customer the prorated amount.
159
+ //
160
+ // Alternative: schedule a Vercel Cron at adjustedNextBilling that resumes
161
+ // the original subscription cleanly and skips the autopay-on-resume.
162
+
163
+ pauseStore.delete(subscriptionId);
164
+
165
+ return {
166
+ resumedAt,
167
+ nextBillingDate: adjustedNextBilling,
168
+ creditAppliedFromPause: record.proratedRefund,
169
+ };
170
+ }
171
+
172
+ // ─────────────────────────────────────────────────────────────────────────────
173
+ // Period-end helper
174
+ // ─────────────────────────────────────────────────────────────────────────────
175
+
176
+ function computePeriodEnd(sub: Preapproval, periodStartMs: number): number {
177
+ const freq = sub.auto_recurring?.frequency ?? 1;
178
+ const type = sub.auto_recurring?.frequency_type ?? "months";
179
+ if (type === "days") return periodStartMs + freq * 86_400_000;
180
+ if (type === "months") return periodStartMs + freq * 30 * 86_400_000;
181
+ return periodStartMs + 30 * 86_400_000;
182
+ }
183
+
184
+ // ─────────────────────────────────────────────────────────────────────────────
185
+ // Dry-run test
186
+ // ─────────────────────────────────────────────────────────────────────────────
187
+
188
+ async function main() {
189
+ const SUB_ID = process.argv[2];
190
+ if (!SUB_ID) {
191
+ console.log("Usage: pnpm tsx 15-prorated-pause-resume.ts <subscription-id>");
192
+ process.exit(1);
193
+ }
194
+ const result = await pauseSubscriptionWithProration({
195
+ subscriptionId: SUB_ID,
196
+ refundUnused: true,
197
+ });
198
+ console.log("Paused:", result);
199
+
200
+ // ... (manually wait, then resume)
201
+
202
+ const resumed = await resumeSubscriptionWithAdjustment(SUB_ID);
203
+ console.log("Resumed:", resumed);
204
+ }
205
+
206
+ if (process.argv[1]?.endsWith("15-prorated-pause-resume.ts")) {
207
+ main().catch((err: unknown) => {
208
+ console.error(err);
209
+ process.exit(1);
210
+ });
211
+ }
@@ -20,6 +20,9 @@ deploy on Vercel as-is.
20
20
  | 10 | `10-cross-package-billing.ts` | One agent loop, 5 packages: identity + attest + MP + facturacion + WhatsApp |
21
21
  | 11 | `11-dunning-sequence.ts` | Failed-payment recovery loop with multi-step dunning + cancel-with-retention |
22
22
  | 12 | `12-reconciliation-pipeline.ts` | Daily MP↔internal-DB reconciliation cron with discrepancy report |
23
+ | 13 | `13-anti-fraud-middleware.ts` | Pre-charge heuristics (CUIT, payer history, velocity, promo abuse) |
24
+ | 14 | `14-marketplace-onboarding.ts` | End-to-end seller-onboarding: CUIT → AFIP → OAuth → test charge → fee |
25
+ | 15 | `15-prorated-pause-resume.ts` | Pause with prorated refund, resume with adjusted next-billing date |
23
26
 
24
27
  ## Conventions
25
28
 
package/dist/cli.cjs ADDED
@@ -0,0 +1,341 @@
1
+ 'use strict';
2
+
3
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
4
+ // src/cli-doctor.ts
5
+ var C = {
6
+ reset: "\x1B[0m",
7
+ dim: "\x1B[2m",
8
+ red: "\x1B[31m",
9
+ green: "\x1B[32m",
10
+ yellow: "\x1B[33m",
11
+ blue: "\x1B[34m",
12
+ magenta: "\x1B[35m",
13
+ cyan: "\x1B[36m",
14
+ bold: "\x1B[1m"
15
+ };
16
+ var NO_COLOR = process.env.NO_COLOR != null || !process.stdout.isTTY;
17
+ var c = (color, s) => NO_COLOR ? s : `${C[color]}${s}${C.reset}`;
18
+ function fmt(r) {
19
+ const icon = r.kind === "ok" ? c("green", "\u2713") : r.kind === "warn" ? c("yellow", "\u26A0") : c("red", "\u2717");
20
+ const detail = r.detail ? `
21
+ ${c("dim", "\u2192 " + r.detail)}` : "";
22
+ return `${icon} ${r.line}${detail}`;
23
+ }
24
+ function checkNode() {
25
+ const major = Number(process.versions.node.split(".")[0]);
26
+ if (major >= 20) {
27
+ return {
28
+ kind: "ok",
29
+ line: `Node ${process.versions.node} (>= 20.0.0)`
30
+ };
31
+ }
32
+ return {
33
+ kind: "fail",
34
+ line: `Node ${process.versions.node} too old`,
35
+ detail: `@ar-agents/mercadopago requires Node 20+. Bun and Edge Runtime are also supported.`
36
+ };
37
+ }
38
+ function checkAccessToken() {
39
+ const t = process.env.MP_ACCESS_TOKEN?.trim();
40
+ if (!t) {
41
+ return {
42
+ kind: "fail",
43
+ line: "MP_ACCESS_TOKEN not set",
44
+ detail: "Get one at https://www.mercadopago.com.ar/developers/panel/app \u2014 TEST- prefix for sandbox, APP_USR- for production."
45
+ };
46
+ }
47
+ if (t.startsWith("TEST-")) {
48
+ return { kind: "ok", line: `MP_ACCESS_TOKEN set (TEST- prefix \u2192 sandbox)` };
49
+ }
50
+ if (t.startsWith("APP_USR-")) {
51
+ return {
52
+ kind: "warn",
53
+ line: `MP_ACCESS_TOKEN set (APP_USR- prefix \u2192 PRODUCTION)`,
54
+ detail: "Live transactions WILL move real money. Use TEST- in development."
55
+ };
56
+ }
57
+ return {
58
+ kind: "fail",
59
+ line: "MP_ACCESS_TOKEN has unexpected prefix",
60
+ detail: `Expected TEST- or APP_USR-, got "${t.slice(0, 8)}\u2026". Common cause: trailing newline in env file (use printf, not echo).`
61
+ };
62
+ }
63
+ async function probeToken(token) {
64
+ try {
65
+ const res = await fetch("https://api.mercadopago.com/users/me", {
66
+ headers: { Authorization: `Bearer ${token}` }
67
+ });
68
+ if (res.status === 401) {
69
+ return {
70
+ kind: "fail",
71
+ line: "Token rejected by MP API (401 Unauthorized)",
72
+ detail: "Token is invalid, expired, or copy-pasted with extra whitespace."
73
+ };
74
+ }
75
+ if (!res.ok) {
76
+ return {
77
+ kind: "fail",
78
+ line: `MP API responded with HTTP ${res.status}`,
79
+ detail: `Unexpected status \u2014 try again or check api.mercadopago.com status.`
80
+ };
81
+ }
82
+ const me = await res.json();
83
+ return {
84
+ kind: "ok",
85
+ line: `Authenticated against api.mercadopago.com`,
86
+ detail: `account ${me.id ?? "?"} \xB7 site ${me.site_id ?? "?"} \xB7 country ${me.country_id ?? "?"}`
87
+ };
88
+ } catch (err) {
89
+ return {
90
+ kind: "fail",
91
+ line: "Could not reach api.mercadopago.com",
92
+ detail: err instanceof Error ? err.message : "Unknown network error. Check connectivity / proxy."
93
+ };
94
+ }
95
+ }
96
+ async function checkPeerDep(name, required) {
97
+ try {
98
+ await import(name);
99
+ return { kind: "ok", line: `${name} installed` };
100
+ } catch {
101
+ return {
102
+ kind: required ? "fail" : "warn",
103
+ line: `${name} not installed`,
104
+ detail: required ? `Required peer dep \u2014 install with: pnpm add ${name}` : `Optional \u2014 required only if you use the matching subpath.`
105
+ };
106
+ }
107
+ }
108
+ function checkBackUrl() {
109
+ const url = process.env.NEXT_PUBLIC_BACK_URL ?? process.env.BACK_URL;
110
+ if (!url) {
111
+ return {
112
+ kind: "warn",
113
+ line: "NEXT_PUBLIC_BACK_URL not set",
114
+ detail: "Required by mercadoPagoTools({ backUrl }) for create_subscription / create_payment_preference. Must be HTTPS (localhost rejected by MP in production)."
115
+ };
116
+ }
117
+ if (!url.startsWith("https://")) {
118
+ return {
119
+ kind: "fail",
120
+ line: `NEXT_PUBLIC_BACK_URL must be HTTPS (got: ${url.slice(0, 40)}\u2026)`,
121
+ detail: "MP rejects localhost and http:// URLs server-side."
122
+ };
123
+ }
124
+ return { kind: "ok", line: `NEXT_PUBLIC_BACK_URL set (${url})` };
125
+ }
126
+ function checkWebhookSecret() {
127
+ const s = process.env.MP_WEBHOOK_SECRET?.trim();
128
+ if (!s) {
129
+ return {
130
+ kind: "warn",
131
+ line: "MP_WEBHOOK_SECRET not set",
132
+ detail: "verifyWebhookSignature() needs this. Copy from https://www.mercadopago.com.ar/developers/panel/app \u2192 notificaciones."
133
+ };
134
+ }
135
+ if (s.length < 16) {
136
+ return {
137
+ kind: "warn",
138
+ line: `MP_WEBHOOK_SECRET set but suspiciously short (${s.length} chars)`,
139
+ detail: "MP secrets are typically 32+ chars. Double-check the paste."
140
+ };
141
+ }
142
+ return { kind: "ok", line: `MP_WEBHOOK_SECRET set (${s.length} chars)` };
143
+ }
144
+ async function loadManifest() {
145
+ const fs = await import('fs/promises');
146
+ for (const rel of ["../tools.manifest.json", "../../tools.manifest.json"]) {
147
+ try {
148
+ const url = new URL(rel, (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
149
+ const text = await fs.readFile(url, "utf-8");
150
+ return JSON.parse(text);
151
+ } catch {
152
+ }
153
+ }
154
+ return null;
155
+ }
156
+ function summarizeManifest(m) {
157
+ const lines = [];
158
+ lines.push(c("bold", `Tools registered: ${m.tools.length}`));
159
+ const groups = /* @__PURE__ */ new Map();
160
+ for (const tool of m.tools) {
161
+ const cat = tool.category ?? inferCategory(tool.name);
162
+ if (!groups.has(cat)) groups.set(cat, []);
163
+ groups.get(cat).push(tool.name);
164
+ }
165
+ for (const [cat, names] of [...groups.entries()].sort()) {
166
+ lines.push(` ${c("dim", "\u2192")} ${cat} (${names.length})`);
167
+ }
168
+ return lines;
169
+ }
170
+ function inferCategory(toolName) {
171
+ if (toolName.includes("subscription") || toolName.includes("preapproval")) return "Subscriptions";
172
+ if (toolName.includes("payment") && !toolName.includes("preference")) return "Payments";
173
+ if (toolName.includes("refund")) return "Refunds";
174
+ if (toolName.includes("preference") || toolName.includes("checkout")) return "Checkout Pro";
175
+ if (toolName.includes("oauth") || toolName.includes("marketplace")) return "Marketplace OAuth";
176
+ if (toolName.includes("merchant_order") || toolName.includes("order")) return "Order Management";
177
+ if (toolName.includes("customer") && !toolName.includes("card")) return "Customers";
178
+ if (toolName.includes("customer_card") || toolName.includes("card")) return "Saved cards";
179
+ if (toolName.includes("installment") || toolName.includes("cuotas") || toolName.includes("promo")) return "Cuotas";
180
+ if (toolName.includes("qr")) return "QR";
181
+ if (toolName.includes("3ds") || toolName.includes("challenge")) return "3DS";
182
+ if (toolName.includes("point")) return "Point devices";
183
+ if (toolName.includes("store") || toolName.includes("pos")) return "Stores+POS";
184
+ if (toolName.includes("balance") || toolName.includes("settlement") || toolName.includes("account")) return "Account/Balance";
185
+ if (toolName.includes("dispute")) return "Disputes";
186
+ if (toolName.includes("webhook")) return "Webhooks";
187
+ if (toolName.includes("bank_account")) return "Bank Accounts";
188
+ if (toolName.includes("lookup") || toolName.includes("validate") || toolName.includes("explain") || toolName.includes("compute")) return "Lookups";
189
+ return "Other";
190
+ }
191
+ var HITL_TOOLS = [
192
+ "refund_payment",
193
+ "cancel_subscription",
194
+ "pause_subscription",
195
+ "cancel_payment_preference",
196
+ "delete_customer_card",
197
+ "cancel_qr_dynamic",
198
+ "delete_pos",
199
+ "revoke_marketplace_token"
200
+ ];
201
+ async function runDoctor(args = { probe: false }) {
202
+ const lines = [];
203
+ lines.push("");
204
+ lines.push(c("bold", `${c("cyan", "@ar-agents/mercadopago")} doctor`));
205
+ lines.push(c("dim", " diagnosing your environment"));
206
+ lines.push("");
207
+ lines.push(fmt(checkNode()));
208
+ const tokenCheck = checkAccessToken();
209
+ lines.push(fmt(tokenCheck));
210
+ if (tokenCheck.kind === "ok" || tokenCheck.kind === "warn") {
211
+ const probe = await probeToken(process.env.MP_ACCESS_TOKEN.trim());
212
+ lines.push(fmt(probe));
213
+ }
214
+ lines.push(fmt(checkBackUrl()));
215
+ lines.push(fmt(checkWebhookSecret()));
216
+ lines.push(fmt(await checkPeerDep("ai", true)));
217
+ lines.push(fmt(await checkPeerDep("zod", true)));
218
+ lines.push(fmt(await checkPeerDep("@vercel/kv", false)));
219
+ lines.push(fmt(await checkPeerDep("@opentelemetry/api", false)));
220
+ lines.push("");
221
+ const manifest = await loadManifest();
222
+ if (manifest) {
223
+ lines.push(...summarizeManifest(manifest));
224
+ lines.push("");
225
+ lines.push(
226
+ c(
227
+ "yellow",
228
+ `${HITL_TOOLS.length} irreversible ops behind requireConfirmation():`
229
+ )
230
+ );
231
+ lines.push(" " + c("dim", HITL_TOOLS.join(" \xB7 ")));
232
+ } else {
233
+ lines.push(
234
+ fmt({
235
+ kind: "warn",
236
+ line: "Could not load tools.manifest.json",
237
+ detail: "The package shipping is incomplete \u2014 reinstall."
238
+ })
239
+ );
240
+ }
241
+ lines.push("");
242
+ if (args.probe && tokenCheck.kind === "ok") {
243
+ lines.push(c("bold", "Probe mode: dry-calling validate_tax_id\u2026"));
244
+ try {
245
+ const res = await fetch("https://api.mercadopago.com/v1/identification_types", {
246
+ headers: { Authorization: `Bearer ${process.env.MP_ACCESS_TOKEN.trim()}` }
247
+ });
248
+ if (res.ok) {
249
+ const types = await res.json();
250
+ lines.push(
251
+ fmt({
252
+ kind: "ok",
253
+ line: `validate_tax_id reachable \u2014 ${types.length} ID types available`
254
+ })
255
+ );
256
+ } else {
257
+ lines.push(
258
+ fmt({
259
+ kind: "warn",
260
+ line: `validate_tax_id probe returned HTTP ${res.status}`
261
+ })
262
+ );
263
+ }
264
+ } catch (err) {
265
+ lines.push(
266
+ fmt({
267
+ kind: "warn",
268
+ line: "Probe failed",
269
+ detail: err instanceof Error ? err.message : String(err)
270
+ })
271
+ );
272
+ }
273
+ lines.push("");
274
+ }
275
+ lines.push(
276
+ c(
277
+ "dim",
278
+ args.probe ? "All probes done. Pass without --probe for the lighter check." : "Run with --probe to also dry-call validate_tax_id (no charge)."
279
+ )
280
+ );
281
+ process.stdout.write(lines.join("\n") + "\n");
282
+ const hasFail = lines.some((l) => l.includes("\u2717"));
283
+ return hasFail ? 1 : 0;
284
+ }
285
+
286
+ // src/cli.ts
287
+ var HELP = `@ar-agents/mercadopago CLI
288
+
289
+ Commands:
290
+ doctor Diagnose your environment (Node, token, peer deps, tools)
291
+ doctor --probe Same as doctor but also dry-calls validate_tax_id
292
+ help Print this message
293
+ version Print the installed package version
294
+
295
+ Environment:
296
+ MP_ACCESS_TOKEN Required for any live calls. TEST- for sandbox, APP_USR- for prod.
297
+ NEXT_PUBLIC_BACK_URL Required HTTPS URL for create_subscription / create_payment_preference.
298
+ MP_WEBHOOK_SECRET Required for verifyWebhookSignature.
299
+
300
+ Docs: https://github.com/ar-agents/ar-agents/tree/main/packages/mercadopago
301
+ `;
302
+ async function readVersion() {
303
+ for (const rel of ["../package.json", "../../package.json"]) {
304
+ try {
305
+ const url = new URL(rel, (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
306
+ const fs = await import('fs/promises');
307
+ const text = await fs.readFile(url, "utf-8");
308
+ const pkg = JSON.parse(text);
309
+ if (pkg.version) return pkg.version;
310
+ } catch {
311
+ }
312
+ }
313
+ return "unknown";
314
+ }
315
+ async function runCli(argv) {
316
+ const [, , cmd, ...rest] = argv;
317
+ if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
318
+ process.stdout.write(HELP);
319
+ return 0;
320
+ }
321
+ if (cmd === "version" || cmd === "--version" || cmd === "-v") {
322
+ process.stdout.write(`@ar-agents/mercadopago ${await readVersion()}
323
+ `);
324
+ return 0;
325
+ }
326
+ if (cmd === "doctor") {
327
+ const probe = rest.includes("--probe");
328
+ return runDoctor({ probe });
329
+ }
330
+ process.stderr.write(
331
+ `Unknown command: ${cmd}
332
+
333
+ Run \`mercadopago help\` for usage.
334
+ `
335
+ );
336
+ return 2;
337
+ }
338
+
339
+ exports.runCli = runCli;
340
+ //# sourceMappingURL=cli.cjs.map
341
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-doctor.ts","../src/cli.ts"],"names":[],"mappings":"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","file":"cli.cjs","sourcesContent":["/**\n * `mercadopago doctor` — diagnostic command for the @ar-agents/mercadopago\n * package. Prints a status report covering:\n *\n * - Node version\n * - MP_ACCESS_TOKEN presence + format + sandbox/prod prefix\n * - Live token validation against `GET /users/me` (lightweight, free)\n * - Peer-dependency presence (ai, zod, @vercel/kv, @opentelemetry/api)\n * - Tools registered (count + categories from tools.manifest.json)\n * - Subpath availability (/vercel-kv, /otel, /testing)\n *\n * No third-party CLI deps. ANSI colors are inlined.\n *\n * Run with:\n * pnpm exec mercadopago doctor\n * npx @ar-agents/mercadopago doctor\n * npx -p @ar-agents/mercadopago mercadopago doctor\n */\n\nconst C = {\n reset: \"\\x1b[0m\",\n dim: \"\\x1b[2m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n bold: \"\\x1b[1m\",\n};\n\nconst NO_COLOR = process.env.NO_COLOR != null || !process.stdout.isTTY;\nconst c = (color: keyof typeof C, s: string) =>\n NO_COLOR ? s : `${C[color]}${s}${C.reset}`;\n\ntype CheckResult =\n | { kind: \"ok\"; line: string; detail?: string }\n | { kind: \"warn\"; line: string; detail?: string }\n | { kind: \"fail\"; line: string; detail?: string };\n\nfunction fmt(r: CheckResult): string {\n const icon =\n r.kind === \"ok\" ? c(\"green\", \"✓\") : r.kind === \"warn\" ? c(\"yellow\", \"⚠\") : c(\"red\", \"✗\");\n const detail = r.detail ? `\\n ${c(\"dim\", \"→ \" + r.detail)}` : \"\";\n return `${icon} ${r.line}${detail}`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Individual checks\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction checkNode(): CheckResult {\n const major = Number(process.versions.node.split(\".\")[0]);\n if (major >= 20) {\n return {\n kind: \"ok\",\n line: `Node ${process.versions.node} (>= 20.0.0)`,\n };\n }\n return {\n kind: \"fail\",\n line: `Node ${process.versions.node} too old`,\n detail: `@ar-agents/mercadopago requires Node 20+. Bun and Edge Runtime are also supported.`,\n };\n}\n\nfunction checkAccessToken(): CheckResult {\n const t = process.env.MP_ACCESS_TOKEN?.trim();\n if (!t) {\n return {\n kind: \"fail\",\n line: \"MP_ACCESS_TOKEN not set\",\n detail:\n \"Get one at https://www.mercadopago.com.ar/developers/panel/app — TEST- prefix for sandbox, APP_USR- for production.\",\n };\n }\n if (t.startsWith(\"TEST-\")) {\n return { kind: \"ok\", line: `MP_ACCESS_TOKEN set (TEST- prefix → sandbox)` };\n }\n if (t.startsWith(\"APP_USR-\")) {\n return {\n kind: \"warn\",\n line: `MP_ACCESS_TOKEN set (APP_USR- prefix → PRODUCTION)`,\n detail: \"Live transactions WILL move real money. Use TEST- in development.\",\n };\n }\n return {\n kind: \"fail\",\n line: \"MP_ACCESS_TOKEN has unexpected prefix\",\n detail: `Expected TEST- or APP_USR-, got \"${t.slice(0, 8)}…\". Common cause: trailing newline in env file (use printf, not echo).`,\n };\n}\n\nasync function probeToken(token: string): Promise<CheckResult> {\n try {\n const res = await fetch(\"https://api.mercadopago.com/users/me\", {\n headers: { Authorization: `Bearer ${token}` },\n });\n if (res.status === 401) {\n return {\n kind: \"fail\",\n line: \"Token rejected by MP API (401 Unauthorized)\",\n detail: \"Token is invalid, expired, or copy-pasted with extra whitespace.\",\n };\n }\n if (!res.ok) {\n return {\n kind: \"fail\",\n line: `MP API responded with HTTP ${res.status}`,\n detail: `Unexpected status — try again or check api.mercadopago.com status.`,\n };\n }\n const me = (await res.json()) as {\n id?: number;\n site_id?: string;\n email?: string;\n country_id?: string;\n };\n return {\n kind: \"ok\",\n line: `Authenticated against api.mercadopago.com`,\n detail: `account ${me.id ?? \"?\"} · site ${me.site_id ?? \"?\"} · country ${me.country_id ?? \"?\"}`,\n };\n } catch (err) {\n return {\n kind: \"fail\",\n line: \"Could not reach api.mercadopago.com\",\n detail:\n err instanceof Error ? err.message : \"Unknown network error. Check connectivity / proxy.\",\n };\n }\n}\n\nasync function checkPeerDep(name: string, required: boolean): Promise<CheckResult> {\n try {\n await import(name);\n return { kind: \"ok\", line: `${name} installed` };\n } catch {\n return {\n kind: required ? \"fail\" : \"warn\",\n line: `${name} not installed`,\n detail: required\n ? `Required peer dep — install with: pnpm add ${name}`\n : `Optional — required only if you use the matching subpath.`,\n };\n }\n}\n\nfunction checkBackUrl(): CheckResult {\n const url = process.env.NEXT_PUBLIC_BACK_URL ?? process.env.BACK_URL;\n if (!url) {\n return {\n kind: \"warn\",\n line: \"NEXT_PUBLIC_BACK_URL not set\",\n detail:\n \"Required by mercadoPagoTools({ backUrl }) for create_subscription / create_payment_preference. Must be HTTPS (localhost rejected by MP in production).\",\n };\n }\n if (!url.startsWith(\"https://\")) {\n return {\n kind: \"fail\",\n line: `NEXT_PUBLIC_BACK_URL must be HTTPS (got: ${url.slice(0, 40)}…)`,\n detail: \"MP rejects localhost and http:// URLs server-side.\",\n };\n }\n return { kind: \"ok\", line: `NEXT_PUBLIC_BACK_URL set (${url})` };\n}\n\nfunction checkWebhookSecret(): CheckResult {\n const s = process.env.MP_WEBHOOK_SECRET?.trim();\n if (!s) {\n return {\n kind: \"warn\",\n line: \"MP_WEBHOOK_SECRET not set\",\n detail:\n \"verifyWebhookSignature() needs this. Copy from https://www.mercadopago.com.ar/developers/panel/app → notificaciones.\",\n };\n }\n if (s.length < 16) {\n return {\n kind: \"warn\",\n line: `MP_WEBHOOK_SECRET set but suspiciously short (${s.length} chars)`,\n detail: \"MP secrets are typically 32+ chars. Double-check the paste.\",\n };\n }\n return { kind: \"ok\", line: `MP_WEBHOOK_SECRET set (${s.length} chars)` };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Tools manifest\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype Manifest = {\n package: string;\n version: string;\n tools: Array<{ name: string; category?: string; description?: string }>;\n};\n\nasync function loadManifest(): Promise<Manifest | null> {\n // Bundled output lives at dist/cli.js. tools.manifest.json sits at the\n // package root, one level up. The src path src/cli-doctor.ts is also one\n // level up. Both resolve via \"../tools.manifest.json\".\n const fs = await import(\"node:fs/promises\");\n for (const rel of [\"../tools.manifest.json\", \"../../tools.manifest.json\"]) {\n try {\n const url = new URL(rel, import.meta.url);\n const text = await fs.readFile(url, \"utf-8\");\n return JSON.parse(text) as Manifest;\n } catch {\n // try next\n }\n }\n return null;\n}\n\nfunction summarizeManifest(m: Manifest): string[] {\n const lines: string[] = [];\n lines.push(c(\"bold\", `Tools registered: ${m.tools.length}`));\n\n // Group by inferred category from name prefix.\n const groups = new Map<string, string[]>();\n for (const tool of m.tools) {\n const cat = tool.category ?? inferCategory(tool.name);\n if (!groups.has(cat)) groups.set(cat, []);\n groups.get(cat)!.push(tool.name);\n }\n for (const [cat, names] of [...groups.entries()].sort()) {\n lines.push(` ${c(\"dim\", \"→\")} ${cat} (${names.length})`);\n }\n return lines;\n}\n\nfunction inferCategory(toolName: string): string {\n if (toolName.includes(\"subscription\") || toolName.includes(\"preapproval\")) return \"Subscriptions\";\n if (toolName.includes(\"payment\") && !toolName.includes(\"preference\")) return \"Payments\";\n if (toolName.includes(\"refund\")) return \"Refunds\";\n if (toolName.includes(\"preference\") || toolName.includes(\"checkout\")) return \"Checkout Pro\";\n if (toolName.includes(\"oauth\") || toolName.includes(\"marketplace\")) return \"Marketplace OAuth\";\n if (toolName.includes(\"merchant_order\") || toolName.includes(\"order\")) return \"Order Management\";\n if (toolName.includes(\"customer\") && !toolName.includes(\"card\")) return \"Customers\";\n if (toolName.includes(\"customer_card\") || toolName.includes(\"card\")) return \"Saved cards\";\n if (toolName.includes(\"installment\") || toolName.includes(\"cuotas\") || toolName.includes(\"promo\")) return \"Cuotas\";\n if (toolName.includes(\"qr\")) return \"QR\";\n if (toolName.includes(\"3ds\") || toolName.includes(\"challenge\")) return \"3DS\";\n if (toolName.includes(\"point\")) return \"Point devices\";\n if (toolName.includes(\"store\") || toolName.includes(\"pos\")) return \"Stores+POS\";\n if (toolName.includes(\"balance\") || toolName.includes(\"settlement\") || toolName.includes(\"account\")) return \"Account/Balance\";\n if (toolName.includes(\"dispute\")) return \"Disputes\";\n if (toolName.includes(\"webhook\")) return \"Webhooks\";\n if (toolName.includes(\"bank_account\")) return \"Bank Accounts\";\n if (toolName.includes(\"lookup\") || toolName.includes(\"validate\") || toolName.includes(\"explain\") || toolName.includes(\"compute\")) return \"Lookups\";\n return \"Other\";\n}\n\nconst HITL_TOOLS = [\n \"refund_payment\",\n \"cancel_subscription\",\n \"pause_subscription\",\n \"cancel_payment_preference\",\n \"delete_customer_card\",\n \"cancel_qr_dynamic\",\n \"delete_pos\",\n \"revoke_marketplace_token\",\n];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Main entrypoint\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport async function runDoctor(args: { probe: boolean } = { probe: false }): Promise<number> {\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(c(\"bold\", `${c(\"cyan\", \"@ar-agents/mercadopago\")} doctor`));\n lines.push(c(\"dim\", \" diagnosing your environment\"));\n lines.push(\"\");\n\n // Environment checks.\n lines.push(fmt(checkNode()));\n\n const tokenCheck = checkAccessToken();\n lines.push(fmt(tokenCheck));\n\n if (tokenCheck.kind === \"ok\" || tokenCheck.kind === \"warn\") {\n const probe = await probeToken(process.env.MP_ACCESS_TOKEN!.trim());\n lines.push(fmt(probe));\n }\n\n lines.push(fmt(checkBackUrl()));\n lines.push(fmt(checkWebhookSecret()));\n\n // Peer deps.\n lines.push(fmt(await checkPeerDep(\"ai\", true)));\n lines.push(fmt(await checkPeerDep(\"zod\", true)));\n lines.push(fmt(await checkPeerDep(\"@vercel/kv\", false)));\n lines.push(fmt(await checkPeerDep(\"@opentelemetry/api\", false)));\n\n lines.push(\"\");\n\n // Tools manifest.\n const manifest = await loadManifest();\n if (manifest) {\n lines.push(...summarizeManifest(manifest));\n lines.push(\"\");\n lines.push(\n c(\n \"yellow\",\n `${HITL_TOOLS.length} irreversible ops behind requireConfirmation():`,\n ),\n );\n lines.push(\" \" + c(\"dim\", HITL_TOOLS.join(\" · \")));\n } else {\n lines.push(\n fmt({\n kind: \"warn\",\n line: \"Could not load tools.manifest.json\",\n detail: \"The package shipping is incomplete — reinstall.\",\n }),\n );\n }\n\n lines.push(\"\");\n\n // Probe mode (extra dry-call).\n if (args.probe && tokenCheck.kind === \"ok\") {\n lines.push(c(\"bold\", \"Probe mode: dry-calling validate_tax_id…\"));\n try {\n const res = await fetch(\"https://api.mercadopago.com/v1/identification_types\", {\n headers: { Authorization: `Bearer ${process.env.MP_ACCESS_TOKEN!.trim()}` },\n });\n if (res.ok) {\n const types = (await res.json()) as Array<{ id: string }>;\n lines.push(\n fmt({\n kind: \"ok\",\n line: `validate_tax_id reachable — ${types.length} ID types available`,\n }),\n );\n } else {\n lines.push(\n fmt({\n kind: \"warn\",\n line: `validate_tax_id probe returned HTTP ${res.status}`,\n }),\n );\n }\n } catch (err) {\n lines.push(\n fmt({\n kind: \"warn\",\n line: \"Probe failed\",\n detail: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n lines.push(\"\");\n }\n\n lines.push(\n c(\n \"dim\",\n args.probe\n ? \"All probes done. Pass without --probe for the lighter check.\"\n : \"Run with --probe to also dry-call validate_tax_id (no charge).\",\n ),\n );\n\n process.stdout.write(lines.join(\"\\n\") + \"\\n\");\n\n // Exit code: 0 if everything was ok or warn, 1 if any fail.\n const hasFail = lines.some((l) => l.includes(\"✗\"));\n return hasFail ? 1 : 0;\n}\n","/**\n * CLI dispatcher for `@ar-agents/mercadopago`. Reads `argv[2]` (the first\n * arg after the bin name) and dispatches to the matching subcommand.\n *\n * Usage:\n * mercadopago doctor — diagnose your environment\n * mercadopago doctor --probe — also dry-call validate_tax_id\n * mercadopago help — print this list\n *\n * Exit codes follow the convention: 0 = ok or warn-only, 1 = at least one\n * fail; CI scripts can rely on `mercadopago doctor` to gate deploys.\n */\n\nimport { runDoctor } from \"./cli-doctor\";\n\nconst HELP = `\\\n@ar-agents/mercadopago CLI\n\nCommands:\n doctor Diagnose your environment (Node, token, peer deps, tools)\n doctor --probe Same as doctor but also dry-calls validate_tax_id\n help Print this message\n version Print the installed package version\n\nEnvironment:\n MP_ACCESS_TOKEN Required for any live calls. TEST- for sandbox, APP_USR- for prod.\n NEXT_PUBLIC_BACK_URL Required HTTPS URL for create_subscription / create_payment_preference.\n MP_WEBHOOK_SECRET Required for verifyWebhookSignature.\n\nDocs: https://github.com/ar-agents/ar-agents/tree/main/packages/mercadopago\n`;\n\nasync function readVersion(): Promise<string> {\n // Bundled output lives at dist/cli.js, so package.json is one level up.\n // (Source path src/cli.ts is also one level up — keeping ../package.json\n // works for both.)\n for (const rel of [\"../package.json\", \"../../package.json\"]) {\n try {\n const url = new URL(rel, import.meta.url);\n const fs = await import(\"node:fs/promises\");\n const text = await fs.readFile(url, \"utf-8\");\n const pkg = JSON.parse(text) as { version?: string };\n if (pkg.version) return pkg.version;\n } catch {\n // try next\n }\n }\n return \"unknown\";\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n const [, , cmd, ...rest] = argv;\n\n if (!cmd || cmd === \"help\" || cmd === \"--help\" || cmd === \"-h\") {\n process.stdout.write(HELP);\n return 0;\n }\n\n if (cmd === \"version\" || cmd === \"--version\" || cmd === \"-v\") {\n process.stdout.write(`@ar-agents/mercadopago ${await readVersion()}\\n`);\n return 0;\n }\n\n if (cmd === \"doctor\") {\n const probe = rest.includes(\"--probe\");\n return runDoctor({ probe });\n }\n\n process.stderr.write(\n `Unknown command: ${cmd}\\n\\nRun \\`mercadopago help\\` for usage.\\n`,\n );\n return 2;\n}\n"]}
package/dist/cli.d.cts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CLI dispatcher for `@ar-agents/mercadopago`. Reads `argv[2]` (the first
3
+ * arg after the bin name) and dispatches to the matching subcommand.
4
+ *
5
+ * Usage:
6
+ * mercadopago doctor — diagnose your environment
7
+ * mercadopago doctor --probe — also dry-call validate_tax_id
8
+ * mercadopago help — print this list
9
+ *
10
+ * Exit codes follow the convention: 0 = ok or warn-only, 1 = at least one
11
+ * fail; CI scripts can rely on `mercadopago doctor` to gate deploys.
12
+ */
13
+ declare function runCli(argv: string[]): Promise<number>;
14
+
15
+ export { runCli };
package/dist/cli.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CLI dispatcher for `@ar-agents/mercadopago`. Reads `argv[2]` (the first
3
+ * arg after the bin name) and dispatches to the matching subcommand.
4
+ *
5
+ * Usage:
6
+ * mercadopago doctor — diagnose your environment
7
+ * mercadopago doctor --probe — also dry-call validate_tax_id
8
+ * mercadopago help — print this list
9
+ *
10
+ * Exit codes follow the convention: 0 = ok or warn-only, 1 = at least one
11
+ * fail; CI scripts can rely on `mercadopago doctor` to gate deploys.
12
+ */
13
+ declare function runCli(argv: string[]): Promise<number>;
14
+
15
+ export { runCli };