@vonpay/checkout-cli 0.3.3 → 0.4.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/README.md CHANGED
@@ -36,12 +36,15 @@ All commands are namespaced under `vonpay checkout`:
36
36
  | `vonpay checkout refunds create` | Refund a captured intent (full or partial) |
37
37
  | `vonpay checkout tokens create` | Create a payment-method token for saved-card / MIT flows |
38
38
  | `vonpay checkout capabilities` | Show what this merchant's binder supports |
39
- | `vonpay checkout trigger <event>` | Trigger a synthetic webhook event against your local endpoint (`session.succeeded`, `session.failed`, `session.expired`, `refund.created`) |
39
+ | `vonpay checkout trigger <event>` | Trigger a synthetic webhook event against your local endpoint (`session.succeeded`, `session.failed`, `refund.created`) |
40
+ | `vonpay checkout listen` | Stream live webhook delivery attempts; optionally re-forward each to a local URL with `--forward-to` |
40
41
  | `vonpay checkout health` | Check API health and latency |
41
42
  | `vonpay checkout doctor` | Diagnose runtime + env + live API probe |
42
43
 
43
44
  Run `vonpay checkout <command> --help` for full flag reference.
44
45
 
46
+ > **`listen --forward-to` signs forwarded events with the v1 scheme** (a fresh `X-VonPay-Timestamp` stamped at forward time + a bare-hex `X-VonPay-Signature` over the body). Verify them in your local handler with `vonpay.webhooks.constructEvent(rawBody, signature, secretKey, timestamp)` — **not** `constructEventV2`. If your subscription is opted into v2 signatures, the forwarded events still use v1; this is a known limitation of local forwarding.
47
+
45
48
  ### Common flags
46
49
 
47
50
  - `--json` on every read/write command for machine-readable output
@@ -1 +1 @@
1
- {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/commands/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAevD"}
1
+ {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/commands/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgBvD"}
@@ -6,6 +6,7 @@ import { refundsCommand } from "./refunds.js";
6
6
  import { tokensCommand } from "./tokens.js";
7
7
  import { capabilitiesCommand } from "./capabilities.js";
8
8
  import { triggerCommand } from "./trigger.js";
9
+ import { listenCommand } from "./listen.js";
9
10
  import { healthCommand } from "./health.js";
10
11
  import { doctorCommand } from "./doctor.js";
11
12
  export function registerCheckout(program) {
@@ -20,6 +21,7 @@ export function registerCheckout(program) {
20
21
  checkout.addCommand(tokensCommand());
21
22
  checkout.addCommand(capabilitiesCommand());
22
23
  checkout.addCommand(triggerCommand());
24
+ checkout.addCommand(listenCommand());
23
25
  checkout.addCommand(healthCommand());
24
26
  checkout.addCommand(doctorCommand());
25
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"checkout.js","sourceRoot":"","sources":["../../src/commands/checkout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,4BAA4B,CAAC,CAAC;IAE7C,QAAQ,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IACnC,QAAQ,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"checkout.js","sourceRoot":"","sources":["../../src/commands/checkout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,4BAA4B,CAAC,CAAC;IAE7C,QAAQ,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IACnC,QAAQ,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * `vonpay checkout listen` — long-lived SSE consumer for the merchant's
4
+ * webhook delivery attempts.
5
+ *
6
+ * Industry conventions followed: WHATWG SSE spec for parsing,
7
+ * Last-Event-ID for reconnect dedupe, exponential backoff, loopback-only
8
+ * forward-to (Stripe CLI posture), refuse-live gate (mirrors
9
+ * `vonpay checkout login --confirm-cli-exposure`), kubectl/gh-style
10
+ * default human output with `--json` opt-in for machine consumption.
11
+ *
12
+ * Output channels:
13
+ * stdout — attempt events (one per delivery), formatted per --json
14
+ * stderr — lifecycle (connecting, reconnecting, shutdown summary)
15
+ *
16
+ * Stdout stays parseable in JSON mode regardless of reconnects.
17
+ */
18
+ export declare function listenCommand(): Command;
19
+ //# sourceMappingURL=listen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listen.d.ts","sourceRoot":"","sources":["../../src/commands/listen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAqOvC"}
@@ -0,0 +1,236 @@
1
+ import { Command } from "commander";
2
+ import { VonPayCheckout } from "@vonpay/checkout-node";
3
+ import { requireApiKey } from "../config.js";
4
+ import { getBaseUrl } from "../client-factory.js";
5
+ import { validateForwardTo } from "../utils/forward-to.js";
6
+ import { consumeSse, SseAuthError, } from "../utils/sse-consumer.js";
7
+ import { formatAttemptHuman, formatAttemptJson, formatLifecycleHuman, formatLifecycleJson, } from "../utils/listen-output.js";
8
+ import { forwardPayload } from "../utils/listen-forward.js";
9
+ /**
10
+ * `vonpay checkout listen` — long-lived SSE consumer for the merchant's
11
+ * webhook delivery attempts.
12
+ *
13
+ * Industry conventions followed: WHATWG SSE spec for parsing,
14
+ * Last-Event-ID for reconnect dedupe, exponential backoff, loopback-only
15
+ * forward-to (Stripe CLI posture), refuse-live gate (mirrors
16
+ * `vonpay checkout login --confirm-cli-exposure`), kubectl/gh-style
17
+ * default human output with `--json` opt-in for machine consumption.
18
+ *
19
+ * Output channels:
20
+ * stdout — attempt events (one per delivery), formatted per --json
21
+ * stderr — lifecycle (connecting, reconnecting, shutdown summary)
22
+ *
23
+ * Stdout stays parseable in JSON mode regardless of reconnects.
24
+ */
25
+ export function listenCommand() {
26
+ return new Command("listen")
27
+ .description("Watch webhook delivery attempts in real time. Optionally re-forward each event to a local URL for development.")
28
+ .option("--forward-to <url>", "Local URL to receive a shadow copy of each delivered event (loopback only by default)")
29
+ .option("--forward-to-tunnel", "Allow non-loopback --forward-to URLs (for ngrok / Cloudflare Tunnel workflows)")
30
+ .option("--events <type>", "Only stream attempts for the given event type. Repeat the flag for multiple types.", (value, prev) => (prev ? [...prev, value] : [value]))
31
+ .option("--json", "Emit one JSON object per line on stdout instead of the colored transcript")
32
+ .option("--api-key <key>", "Override the API key from env / config")
33
+ .option("--confirm-live", "Acknowledge that the listen stream may surface production webhook attempts (required for vp_sk_live_* keys)")
34
+ .action(async (opts) => {
35
+ const apiKey = opts.apiKey ?? requireApiKey();
36
+ if (apiKey.startsWith("vp_sk_live_") && !opts.confirmLive) {
37
+ process.stderr.write(formatLifecycleHuman("Refusing to start listen with a live key (vp_sk_live_*). Re-run with --confirm-live to acknowledge that production webhook attempts will stream to this terminal.", "error") + "\n");
38
+ process.exit(1);
39
+ }
40
+ if (!apiKey.startsWith("vp_sk_test_") &&
41
+ !apiKey.startsWith("vp_sk_live_")) {
42
+ process.stderr.write(formatLifecycleHuman("Listen requires a secret key (vp_sk_*). Publishable keys are rejected by the server.", "error") + "\n");
43
+ process.exit(1);
44
+ }
45
+ let forwardUrl;
46
+ let forwardWarning;
47
+ if (opts.forwardTo) {
48
+ const verdict = validateForwardTo(opts.forwardTo, {
49
+ allowTunnel: opts.forwardToTunnel === true,
50
+ });
51
+ if (!verdict.ok) {
52
+ process.stderr.write(formatLifecycleHuman(verdict.reason, "error") + "\n");
53
+ process.exit(1);
54
+ }
55
+ forwardUrl = verdict.url;
56
+ forwardWarning = verdict.warning;
57
+ }
58
+ // Build the SSE URL from the SDK's resolved base URL — honors
59
+ // VONPAY_BASE_URL / config.json baseUrl overrides used by the rest
60
+ // of the CLI commands.
61
+ const baseUrl = (getBaseUrl() ?? "https://checkout.vonpay.com").replace(/\/+$/, "");
62
+ const sseUrl = new URL(`${baseUrl}/v1/webhook_listen`);
63
+ if (opts.events && opts.events.length > 0) {
64
+ sseUrl.searchParams.set("event_types", opts.events.join(","));
65
+ }
66
+ // SDK client for the per-attempt fetchEvent calls (only used when --forward-to is set)
67
+ const sdk = forwardUrl
68
+ ? new VonPayCheckout({ apiKey, baseUrl })
69
+ : null;
70
+ const controller = new AbortController();
71
+ let eventCount = 0;
72
+ const startedAt = Date.now();
73
+ const mode = opts.json === true ? "json" : "human";
74
+ const onSignal = (sig) => {
75
+ const elapsedSec = Math.round((Date.now() - startedAt) / 1000);
76
+ if (mode === "human") {
77
+ process.stderr.write("\n" +
78
+ formatLifecycleHuman(`Shutting down (${sig}). Received ${eventCount} event${eventCount === 1 ? "" : "s"} in ${elapsedSec}s.`, "info") +
79
+ "\n");
80
+ }
81
+ else {
82
+ process.stderr.write(formatLifecycleJson("shutdown", {
83
+ signal: sig,
84
+ event_count: eventCount,
85
+ elapsed_seconds: elapsedSec,
86
+ }) + "\n");
87
+ }
88
+ controller.abort();
89
+ };
90
+ process.once("SIGINT", () => onSignal("SIGINT"));
91
+ process.once("SIGTERM", () => onSignal("SIGTERM"));
92
+ const onLifecycle = (event) => {
93
+ if (mode === "json") {
94
+ process.stderr.write(formatLifecycleJson(event.kind, lifecyclePayload(event)) + "\n");
95
+ return;
96
+ }
97
+ process.stderr.write(formatLifecycleHuman(lifecycleHumanMessage(event), lifecycleSeverity(event.kind)) + "\n");
98
+ };
99
+ // Pre-stream, emitted directly rather than through onLifecycle —
100
+ // "warning" is not a LifecycleEvent kind (it's a one-shot forward-target
101
+ // caveat, not a connection-lifecycle transition), so it intentionally
102
+ // bypasses the onLifecycle/lifecyclePayload path.
103
+ if (forwardWarning) {
104
+ process.stderr.write(mode === "human"
105
+ ? formatLifecycleHuman(forwardWarning, "warn") + "\n"
106
+ : formatLifecycleJson("warning", { message: forwardWarning }) + "\n");
107
+ }
108
+ if (mode === "human") {
109
+ const filterNote = opts.events?.length
110
+ ? ` (filtered to ${opts.events.join(", ")})`
111
+ : "";
112
+ const fwdNote = forwardUrl ? ` → forwarding to ${forwardUrl.toString()}` : "";
113
+ process.stderr.write(formatLifecycleHuman(`Ready! Listening for webhook delivery attempts${filterNote}${fwdNote}.`, "info") + "\n");
114
+ }
115
+ else {
116
+ process.stderr.write(formatLifecycleJson("ready", {
117
+ base_url: baseUrl,
118
+ filter: opts.events ?? null,
119
+ forward_to: forwardUrl?.toString() ?? null,
120
+ }) + "\n");
121
+ }
122
+ try {
123
+ for await (const sseEvent of consumeSse({
124
+ url: sseUrl.toString(),
125
+ headers: { Authorization: `Bearer ${apiKey}` },
126
+ signal: controller.signal,
127
+ onLifecycle,
128
+ })) {
129
+ if (sseEvent.type === "timeout") {
130
+ // Server-ceiling. The consumer reconnects transparently —
131
+ // surface as a lifecycle note, not a stream event.
132
+ onLifecycle({
133
+ kind: "disconnected",
134
+ reason: "server-ceiling (1h cap; auto-reconnecting)",
135
+ willRetryInMs: 0,
136
+ });
137
+ continue;
138
+ }
139
+ if (sseEvent.type !== "webhook.attempt") {
140
+ // Future-compatible: skip unknown event types so an additive
141
+ // server-side surface doesn't break older CLI versions.
142
+ continue;
143
+ }
144
+ let payload;
145
+ try {
146
+ payload = JSON.parse(sseEvent.data);
147
+ }
148
+ catch {
149
+ continue; // malformed frame; skip
150
+ }
151
+ eventCount += 1;
152
+ let forwardOutcome = null;
153
+ if (forwardUrl && sdk) {
154
+ try {
155
+ const eventRecord = await sdk.webhookEvents.retrieve(payload.event_id);
156
+ forwardOutcome = await forwardPayload(eventRecord.payload, {
157
+ url: forwardUrl,
158
+ signingSecret: apiKey,
159
+ signal: controller.signal,
160
+ });
161
+ }
162
+ catch (err) {
163
+ const message = err instanceof Error ? err.message : String(err);
164
+ forwardOutcome = {
165
+ attempted: true,
166
+ status: null,
167
+ latencyMs: null,
168
+ error: `fetch-event failed: ${message.slice(0, 200)}`,
169
+ };
170
+ }
171
+ }
172
+ if (mode === "human") {
173
+ process.stdout.write(formatAttemptHuman(payload, forwardOutcome) + "\n");
174
+ }
175
+ else {
176
+ process.stdout.write(formatAttemptJson(payload, forwardOutcome) + "\n");
177
+ }
178
+ }
179
+ }
180
+ catch (err) {
181
+ if (err instanceof SseAuthError) {
182
+ if (mode === "human") {
183
+ process.stderr.write(formatLifecycleHuman(`Authentication failed (HTTP ${err.status}). Run \`vonpay checkout login\` with a valid secret key.`, "error") + "\n");
184
+ }
185
+ else {
186
+ process.stderr.write(formatLifecycleJson("auth_failed", { status: err.status }) + "\n");
187
+ }
188
+ process.exit(1);
189
+ }
190
+ throw err;
191
+ }
192
+ });
193
+ }
194
+ function lifecyclePayload(event) {
195
+ switch (event.kind) {
196
+ case "connecting":
197
+ return { last_event_id: event.lastEventId ?? null };
198
+ case "connected":
199
+ return {};
200
+ case "disconnected":
201
+ return { reason: event.reason, will_retry_in_ms: event.willRetryInMs };
202
+ case "auth_failed":
203
+ return { status: event.status };
204
+ case "fatal":
205
+ return { error: event.error.message };
206
+ }
207
+ }
208
+ function lifecycleHumanMessage(event) {
209
+ switch (event.kind) {
210
+ case "connecting":
211
+ return event.lastEventId
212
+ ? `Reconnecting (resume from ${event.lastEventId})`
213
+ : "Connecting...";
214
+ case "connected":
215
+ return "Connected.";
216
+ case "disconnected":
217
+ return `Disconnected: ${event.reason}. Retrying in ${event.willRetryInMs}ms.`;
218
+ case "auth_failed":
219
+ return `Authentication failed (HTTP ${event.status}).`;
220
+ case "fatal":
221
+ return `Fatal: ${event.error.message}`;
222
+ }
223
+ }
224
+ function lifecycleSeverity(kind) {
225
+ switch (kind) {
226
+ case "connecting":
227
+ case "connected":
228
+ return "info";
229
+ case "disconnected":
230
+ return "warn";
231
+ case "auth_failed":
232
+ case "fatal":
233
+ return "error";
234
+ }
235
+ }
236
+ //# sourceMappingURL=listen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listen.js","sourceRoot":"","sources":["../../src/commands/listen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,YAAY,GAEb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAW5D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;SACzB,WAAW,CACV,gHAAgH,CACjH;SACA,MAAM,CACL,oBAAoB,EACpB,uFAAuF,CACxF;SACA,MAAM,CACL,qBAAqB,EACrB,gFAAgF,CACjF;SACA,MAAM,CACL,iBAAiB,EACjB,oFAAoF,EACpF,CAAC,KAAa,EAAE,IAA0B,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnF;SACA,MAAM,CAAC,QAAQ,EAAE,2EAA2E,CAAC;SAC7F,MAAM,CAAC,iBAAiB,EAAE,wCAAwC,CAAC;SACnE,MAAM,CACL,gBAAgB,EAChB,6GAA6G,CAC9G;SACA,MAAM,CAAC,KAAK,EAAE,IAAmB,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;QAE9C,IAAI,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,CAClB,mKAAmK,EACnK,OAAO,CACR,GAAG,IAAI,CACT,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IACE,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC;YACjC,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,EACjC,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,CAClB,sFAAsF,EACtF,OAAO,CACR,GAAG,IAAI,CACT,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,UAA2B,CAAC;QAChC,IAAI,cAAkC,CAAC;QACvC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE;gBAChD,WAAW,EAAE,IAAI,CAAC,eAAe,KAAK,IAAI;aAC3C,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CACrD,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;YACzB,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;QACnC,CAAC;QAED,8DAA8D;QAC9D,mEAAmE;QACnE,uBAAuB;QACvB,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,IAAI,6BAA6B,CAAC,CAAC,OAAO,CACrE,MAAM,EACN,EAAE,CACH,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO,oBAAoB,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,uFAAuF;QACvF,MAAM,GAAG,GAAG,UAAU;YACpB,CAAC,CAAC,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YACzC,CAAC,CAAC,IAAI,CAAC;QAET,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAqB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAErE,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAQ,EAAE;YACrC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;YAC/D,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI;oBACF,oBAAoB,CAClB,kBAAkB,GAAG,eAAe,UAAU,SAAS,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,UAAU,IAAI,EACvG,MAAM,CACP;oBACD,IAAI,CACP,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mBAAmB,CAAC,UAAU,EAAE;oBAC9B,MAAM,EAAE,GAAG;oBACX,WAAW,EAAE,UAAU;oBACvB,eAAe,EAAE,UAAU;iBAC5B,CAAC,GAAG,IAAI,CACV,CAAC;YACJ,CAAC;YACD,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QAEnD,MAAM,WAAW,GAAG,CAAC,KAAqB,EAAQ,EAAE;YAClD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAChE,CAAC;gBACF,OAAO;YACT,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACjH,CAAC,CAAC;QAEF,iEAAiE;QACjE,yEAAyE;QACzE,sEAAsE;QACtE,kDAAkD;QAClD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,KAAK,OAAO;gBACd,CAAC,CAAC,oBAAoB,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG,IAAI;gBACrD,CAAC,CAAC,mBAAmB,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,GAAG,IAAI,CACvE,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM;gBACpC,CAAC,CAAC,iBAAiB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAC5C,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,oBAAoB,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,CAAC,iDAAiD,UAAU,GAAG,OAAO,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,CAC9G,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mBAAmB,CAAC,OAAO,EAAE;gBAC3B,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;gBAC3B,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,IAAI;aAC3C,CAAC,GAAG,IAAI,CACV,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,UAAU,CAAC;gBACtC,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE;gBACtB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE;gBAC9C,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,WAAW;aACZ,CAAC,EAAE,CAAC;gBACH,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAChC,0DAA0D;oBAC1D,mDAAmD;oBACnD,WAAW,CAAC;wBACV,IAAI,EAAE,cAAc;wBACpB,MAAM,EAAE,4CAA4C;wBACpD,aAAa,EAAE,CAAC;qBACjB,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBACD,IAAI,QAAQ,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACxC,6DAA6D;oBAC7D,wDAAwD;oBACxD,SAAS;gBACX,CAAC;gBAED,IAAI,OAA8B,CAAC;gBACnC,IAAI,CAAC;oBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAA0B,CAAC;gBAC/D,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS,CAAC,wBAAwB;gBACpC,CAAC;gBAED,UAAU,IAAI,CAAC,CAAC;gBAChB,IAAI,cAAc,GAAG,IAAI,CAAC;gBAC1B,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;oBACtB,IAAI,CAAC;wBACH,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;wBACvE,cAAc,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,OAAO,EAAE;4BACzD,GAAG,EAAE,UAAU;4BACf,aAAa,EAAE,MAAM;4BACrB,MAAM,EAAE,UAAU,CAAC,MAAM;yBAC1B,CAAC,CAAC;oBACL,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;wBACjE,cAAc,GAAG;4BACf,SAAS,EAAE,IAAI;4BACf,MAAM,EAAE,IAAI;4BACZ,SAAS,EAAE,IAAI;4BACf,KAAK,EAAE,uBAAuB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;yBACtD,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,OAAO,EAAE,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC3E,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC1E,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,YAAY,EAAE,CAAC;gBAChC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,CAClB,+BAA+B,GAAG,CAAC,MAAM,2DAA2D,EACpG,OAAO,CACR,GAAG,IAAI,CACT,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mBAAmB,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAClE,CAAC;gBACJ,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAqB;IAC7C,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,YAAY;YACf,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC;QACtD,KAAK,WAAW;YACd,OAAO,EAAE,CAAC;QACZ,KAAK,cAAc;YACjB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC;QACzE,KAAK,aAAa;YAChB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,OAAO;YACV,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAqB;IAClD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,YAAY;YACf,OAAO,KAAK,CAAC,WAAW;gBACtB,CAAC,CAAC,6BAA6B,KAAK,CAAC,WAAW,GAAG;gBACnD,CAAC,CAAC,eAAe,CAAC;QACtB,KAAK,WAAW;YACd,OAAO,YAAY,CAAC;QACtB,KAAK,cAAc;YACjB,OAAO,iBAAiB,KAAK,CAAC,MAAM,iBAAiB,KAAK,CAAC,aAAa,KAAK,CAAC;QAChF,KAAK,aAAa;YAChB,OAAO,+BAA+B,KAAK,CAAC,MAAM,IAAI,CAAC;QACzD,KAAK,OAAO;YACV,OAAO,UAAU,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAA4B;IACrD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY,CAAC;QAClB,KAAK,WAAW;YACd,OAAO,MAAM,CAAC;QAChB,KAAK,cAAc;YACjB,OAAO,MAAM,CAAC;QAChB,KAAK,aAAa,CAAC;QACnB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -1,3 +1,23 @@
1
1
  import { Command } from "commander";
2
+ export declare const SUPPORTED_EVENTS: readonly ["session.succeeded", "session.failed", "payment_intent.succeeded", "payment_intent.failed", "payment_intent.cancelled", "refund.created"];
3
+ type SupportedEvent = (typeof SUPPORTED_EVENTS)[number];
4
+ interface TriggerPayload {
5
+ event: SupportedEvent;
6
+ sessionId: string;
7
+ merchantId: string;
8
+ amount: number;
9
+ currency: string;
10
+ status: string;
11
+ timestamp: string;
12
+ transactionId?: string;
13
+ refundId?: string;
14
+ paymentIntentId?: string;
15
+ }
16
+ export declare function buildPayload(event: SupportedEvent, opts: {
17
+ sessionId?: string;
18
+ amount?: number;
19
+ currency?: string;
20
+ }): TriggerPayload;
2
21
  export declare function triggerCommand(): Command;
22
+ export {};
3
23
  //# sourceMappingURL=trigger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0DpC,wBAAgB,cAAc,IAAI,OAAO,CA0ExC"}
1
+ {"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,gBAAgB,qJAOnB,CAAC;AACX,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAWxD,UAAU,cAAc;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,cAAc,CA4BhB;AAED,wBAAgB,cAAc,IAAI,OAAO,CA0ExC"}
@@ -3,21 +3,30 @@ import { createHmac, randomUUID } from "node:crypto";
3
3
  import chalk from "chalk";
4
4
  import ora from "ora";
5
5
  import { requireApiKey } from "../config.js";
6
- const SUPPORTED_EVENTS = [
6
+ export const SUPPORTED_EVENTS = [
7
7
  "session.succeeded",
8
8
  "session.failed",
9
- "session.expired",
9
+ "payment_intent.succeeded",
10
+ "payment_intent.failed",
11
+ "payment_intent.cancelled",
10
12
  "refund.created",
11
13
  ];
12
14
  const STATUS_BY_EVENT = {
13
15
  "session.succeeded": "succeeded",
14
16
  "session.failed": "failed",
15
- "session.expired": "expired",
17
+ "payment_intent.succeeded": "succeeded",
18
+ "payment_intent.failed": "failed",
19
+ "payment_intent.cancelled": "cancelled",
16
20
  "refund.created": "created",
17
21
  };
18
- function buildPayload(event, opts) {
19
- const hasTransaction = event === "session.succeeded" || event === "refund.created";
22
+ export function buildPayload(event, opts) {
23
+ const isPaymentIntent = event.startsWith("payment_intent.");
20
24
  const isRefund = event === "refund.created";
25
+ // A transaction row is written for any terminal success — a settled
26
+ // session, a captured payment intent, or a refund.
27
+ const hasTransaction = event === "session.succeeded" ||
28
+ event === "payment_intent.succeeded" ||
29
+ isRefund;
21
30
  const payload = {
22
31
  event,
23
32
  sessionId: opts.sessionId ?? `session_test_${randomUUID().slice(0, 8)}`,
@@ -33,6 +42,9 @@ function buildPayload(event, opts) {
33
42
  if (isRefund) {
34
43
  payload.refundId = `re_test_${randomUUID().slice(0, 8)}`;
35
44
  }
45
+ if (isPaymentIntent) {
46
+ payload.paymentIntentId = `vpi_test_${randomUUID().slice(0, 8)}`;
47
+ }
36
48
  return payload;
37
49
  }
38
50
  export function triggerCommand() {
@@ -1 +1 @@
1
- {"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * URL validation for `vonpay checkout listen --forward-to`.
3
+ *
4
+ * Default posture: loopback-only. Refuses any URL whose hostname is not
5
+ * one of the IPv4/IPv6 loopback aliases. This protects against the
6
+ * "I typed the prod URL by mistake" class of incident, where a dev
7
+ * starts forwarding production webhook attempts at their staging
8
+ * endpoint or a public colleague's URL.
9
+ *
10
+ * The opt-in --forward-to-tunnel flag allows non-loopback hosts for
11
+ * ngrok / Cloudflare Tunnel workflows. When set, only `https://` is
12
+ * additionally rejected for non-loopback — http on a public host is
13
+ * a stronger anti-pattern than tunneled https.
14
+ *
15
+ * Scheme: http and https accepted on loopback; non-loopback requires
16
+ * the tunnel flag.
17
+ */
18
+ export type ForwardToVerdict = {
19
+ ok: true;
20
+ url: URL;
21
+ isLoopback: boolean;
22
+ warning?: string;
23
+ } | {
24
+ ok: false;
25
+ reason: string;
26
+ };
27
+ /**
28
+ * Pure validator. No I/O. Caller decides what to do with the verdict
29
+ * (the CLI surfaces `reason` to stderr and exits non-zero).
30
+ */
31
+ export declare function validateForwardTo(raw: string, opts: {
32
+ allowTunnel: boolean;
33
+ }): ForwardToVerdict;
34
+ //# sourceMappingURL=forward-to.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward-to.d.ts","sourceRoot":"","sources":["../../src/utils/forward-to.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAmBH,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,GAAG,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,WAAW,EAAE,OAAO,CAAA;CAAE,GAC7B,gBAAgB,CA6ClB"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * URL validation for `vonpay checkout listen --forward-to`.
3
+ *
4
+ * Default posture: loopback-only. Refuses any URL whose hostname is not
5
+ * one of the IPv4/IPv6 loopback aliases. This protects against the
6
+ * "I typed the prod URL by mistake" class of incident, where a dev
7
+ * starts forwarding production webhook attempts at their staging
8
+ * endpoint or a public colleague's URL.
9
+ *
10
+ * The opt-in --forward-to-tunnel flag allows non-loopback hosts for
11
+ * ngrok / Cloudflare Tunnel workflows. When set, only `https://` is
12
+ * additionally rejected for non-loopback — http on a public host is
13
+ * a stronger anti-pattern than tunneled https.
14
+ *
15
+ * Scheme: http and https accepted on loopback; non-loopback requires
16
+ * the tunnel flag.
17
+ */
18
+ const LOOPBACK_HOSTS = new Set([
19
+ "localhost",
20
+ "127.0.0.1",
21
+ "0.0.0.0", // kernel-wildcard often routes to loopback on Linux / macOS dev hosts
22
+ "::1",
23
+ // URL.hostname surrounds IPv6 with brackets, but the bracket-stripping
24
+ // happens before this set is consulted (see normalizeHost). Both forms
25
+ // listed for defensiveness.
26
+ "[::1]",
27
+ // IPv6-mapped IPv4 loopback. Node's URL parser normalizes
28
+ // `[::ffff:127.0.0.1]` to either form depending on version — both
29
+ // are functionally loopback so we list every variant we have
30
+ // observed in the wild.
31
+ "::ffff:127.0.0.1",
32
+ "::ffff:7f00:1",
33
+ ]);
34
+ /**
35
+ * Pure validator. No I/O. Caller decides what to do with the verdict
36
+ * (the CLI surfaces `reason` to stderr and exits non-zero).
37
+ */
38
+ export function validateForwardTo(raw, opts) {
39
+ if (typeof raw !== "string" || raw.length === 0) {
40
+ return { ok: false, reason: "--forward-to URL is required" };
41
+ }
42
+ let url;
43
+ try {
44
+ url = new URL(raw);
45
+ }
46
+ catch {
47
+ return {
48
+ ok: false,
49
+ reason: `--forward-to is not a parseable URL: ${truncate(raw)}`,
50
+ };
51
+ }
52
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
53
+ return {
54
+ ok: false,
55
+ reason: `--forward-to scheme must be http or https; got ${url.protocol}`,
56
+ };
57
+ }
58
+ const host = normalizeHost(url.hostname);
59
+ const isLoopback = LOOPBACK_HOSTS.has(host);
60
+ if (!isLoopback && !opts.allowTunnel) {
61
+ return {
62
+ ok: false,
63
+ reason: `--forward-to refuses non-loopback hosts by default (got ${url.hostname}). ` +
64
+ `Re-run with --forward-to-tunnel if forwarding through ngrok / Cloudflare Tunnel / etc.`,
65
+ };
66
+ }
67
+ // `0.0.0.0` is treated as loopback for dev convenience, but it's a
68
+ // bind-wildcard, not a guaranteed destination — in some container /
69
+ // network configs an outbound connection to 0.0.0.0 routes off-host.
70
+ // Accept it (non-breaking) but warn so a dev who meant "localhost"
71
+ // isn't silently forwarding off-loopback.
72
+ const warning = host === "0.0.0.0"
73
+ ? "forwarding to 0.0.0.0 — that's a bind-wildcard, not a guaranteed loopback destination (it can route off-host in some container/network setups). Prefer 127.0.0.1 or localhost if you meant your local machine."
74
+ : undefined;
75
+ return { ok: true, url, isLoopback, warning };
76
+ }
77
+ function normalizeHost(hostname) {
78
+ // URL.hostname returns IPv6 addresses unwrapped (no brackets), but
79
+ // dual-coverage doesn't hurt.
80
+ if (hostname.startsWith("[") && hostname.endsWith("]")) {
81
+ return hostname.slice(1, -1);
82
+ }
83
+ return hostname.toLowerCase();
84
+ }
85
+ function truncate(s) {
86
+ return s.length <= 120 ? s : `${s.slice(0, 117)}...`;
87
+ }
88
+ //# sourceMappingURL=forward-to.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward-to.js","sourceRoot":"","sources":["../../src/utils/forward-to.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,WAAW;IACX,WAAW;IACX,SAAS,EAAE,sEAAsE;IACjF,KAAK;IACL,uEAAuE;IACvE,uEAAuE;IACvE,4BAA4B;IAC5B,OAAO;IACP,0DAA0D;IAC1D,kEAAkE;IAClE,6DAA6D;IAC7D,wBAAwB;IACxB,kBAAkB;IAClB,eAAe;CAChB,CAAC,CAAC;AAMH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,IAA8B;IAE9B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,wCAAwC,QAAQ,CAAC,GAAG,CAAC,EAAE;SAChE,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,kDAAkD,GAAG,CAAC,QAAQ,EAAE;SACzE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE5C,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,2DAA2D,GAAG,CAAC,QAAQ,KAAK;gBAC5E,wFAAwF;SAC3F,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,oEAAoE;IACpE,qEAAqE;IACrE,mEAAmE;IACnE,0CAA0C;IAC1C,MAAM,OAAO,GACX,IAAI,KAAK,SAAS;QAChB,CAAC,CAAC,gNAAgN;QAClN,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,mEAAmE;IACnE,8BAA8B;IAC9B,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC;AACvD,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { ForwardOutcome } from "./listen-output.js";
2
+ /**
3
+ * Shadow-forward a webhook event to a local URL.
4
+ *
5
+ * The CLI receives a delivery-attempt TRANSCRIPT over SSE — not the
6
+ * payload itself. To replay the same delivery against a local URL,
7
+ * the CLI:
8
+ *
9
+ * 1. Fetches the full event record via GET /v1/webhook_events/:id
10
+ * (the public webhook-event read endpoint)
11
+ * 2. Computes an HMAC-SHA256 signature over the body using the
12
+ * merchant's API key (same secret-equals-key convention the SDK's
13
+ * `webhooks.constructEvent` verifies)
14
+ * 3. POSTs to the local URL with `X-VonPay-Signature` +
15
+ * `X-VonPay-Timestamp` headers, matching the live delivery shape.
16
+ * The timestamp is stamped HERE, at forward time — see the
17
+ * `forwardPayload` body for the fresh-timestamp rationale.
18
+ *
19
+ * Bounded by a per-forward timeout (default 5s) and never retries —
20
+ * shadow-forward is best-effort; if the local URL is down, the
21
+ * transcript line shows the failure and the dev moves on.
22
+ *
23
+ * This re-delivers from the SSE delivery transcript, which differs from
24
+ * Stripe CLI's `stripe listen --forward-to` pre-empt model.
25
+ */
26
+ interface ForwardOptions {
27
+ /** Local URL to POST the payload to. */
28
+ url: URL;
29
+ /** Merchant API key (vp_sk_*) — used as HMAC secret. */
30
+ signingSecret: string;
31
+ /** Per-forward timeout. Default 5_000. */
32
+ timeoutMs?: number;
33
+ /** AbortSignal for graceful shutdown. */
34
+ signal: AbortSignal;
35
+ }
36
+ /**
37
+ * Sign + POST a JSON payload to the local URL. Returns an outcome
38
+ * shape that the output formatters render — never throws (errors
39
+ * surface via `outcome.error`).
40
+ */
41
+ export declare function forwardPayload(payload: Record<string, unknown>, opts: ForwardOptions): Promise<ForwardOutcome>;
42
+ export {};
43
+ //# sourceMappingURL=listen-forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listen-forward.d.ts","sourceRoot":"","sources":["../../src/utils/listen-forward.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,UAAU,cAAc;IACtB,wCAAwC;IACxC,GAAG,EAAE,GAAG,CAAC;IACT,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,cAAc,CAAC,CA8DzB"}