@sendly/cli 3.32.0 → 3.34.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.
@@ -0,0 +1,17 @@
1
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
2
+ export default class WebhooksBackfill extends AuthenticatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ since: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ until: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ "event-types": import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ limit: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
+ json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,73 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
3
+ import { apiClient } from "../../lib/api-client.js";
4
+ import { success, error, spinner, json, isJsonMode } from "../../lib/output.js";
5
+ export default class WebhooksBackfill extends AuthenticatedCommand {
6
+ static description = "Synthesize missed webhook events from the message log. Use when an outage left events with no audit row.";
7
+ static examples = [
8
+ "<%= config.bin %> webhooks backfill whk_abc123",
9
+ "<%= config.bin %> webhooks backfill whk_abc123 --since 2026-05-01T00:00:00Z --limit 5000",
10
+ "<%= config.bin %> webhooks backfill whk_abc123 --event-types message.delivered,message.failed",
11
+ ];
12
+ static args = {
13
+ id: Args.string({ description: "Webhook ID", required: true }),
14
+ };
15
+ static flags = {
16
+ ...AuthenticatedCommand.baseFlags,
17
+ since: Flags.string({
18
+ description: "Earliest message time (ISO-8601). Default: now − 24h.",
19
+ }),
20
+ until: Flags.string({
21
+ description: "Latest message time (ISO-8601). Default: now.",
22
+ }),
23
+ "event-types": Flags.string({
24
+ description: "Comma-separated event types to backfill (message.sent, message.delivered, message.failed)",
25
+ }),
26
+ limit: Flags.integer({
27
+ description: "Maximum events to synthesize (max 10000)",
28
+ default: 1000,
29
+ }),
30
+ };
31
+ async run() {
32
+ const { args, flags } = await this.parse(WebhooksBackfill);
33
+ const body = {};
34
+ if (flags.since)
35
+ body.since = flags.since;
36
+ if (flags.until)
37
+ body.until = flags.until;
38
+ if (flags["event-types"])
39
+ body.event_types = flags["event-types"]
40
+ .split(",")
41
+ .map((s) => s.trim())
42
+ .filter(Boolean);
43
+ if (flags.limit !== undefined)
44
+ body.limit = flags.limit;
45
+ const sp = spinner("Synthesizing missed deliveries...");
46
+ sp.start();
47
+ try {
48
+ const result = await apiClient.post(`/api/v1/webhooks/${args.id}/backfill`, body);
49
+ sp.stop();
50
+ if (isJsonMode()) {
51
+ json(result);
52
+ return;
53
+ }
54
+ const byType = Object.entries(result.by_type ?? {})
55
+ .map(([k, v]) => `${k}=${v}`)
56
+ .join(", ");
57
+ success(result.message || "Backfill complete", {
58
+ Synthesized: String(result.synthesized),
59
+ "By Type": byType || "(none)",
60
+ "Candidates Scanned": String(result.candidates_scanned),
61
+ Truncated: result.truncated ? "yes (more eligible than limit)" : "no",
62
+ Window: `${result.since} → ${result.until}`,
63
+ Limit: String(result.limit),
64
+ });
65
+ }
66
+ catch (err) {
67
+ sp.stop();
68
+ error(`Failed to backfill: ${err instanceof Error ? err.message : String(err)}`);
69
+ this.exit(1);
70
+ }
71
+ }
72
+ }
73
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2ZpbGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tbWFuZHMvd2ViaG9va3MvYmFja2ZpbGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDMUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFjaEYsTUFBTSxDQUFDLE9BQU8sT0FBTyxnQkFBaUIsU0FBUSxvQkFBb0I7SUFDaEUsTUFBTSxDQUFDLFdBQVcsR0FDaEIsMEdBQTBHLENBQUM7SUFFN0csTUFBTSxDQUFDLFFBQVEsR0FBRztRQUNoQixnREFBZ0Q7UUFDaEQsMEZBQTBGO1FBQzFGLCtGQUErRjtLQUNoRyxDQUFDO0lBRUYsTUFBTSxDQUFDLElBQUksR0FBRztRQUNaLEVBQUUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7S0FDL0QsQ0FBQztJQUVGLE1BQU0sQ0FBQyxLQUFLLEdBQUc7UUFDYixHQUFHLG9CQUFvQixDQUFDLFNBQVM7UUFDakMsS0FBSyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDbEIsV0FBVyxFQUFFLHVEQUF1RDtTQUNyRSxDQUFDO1FBQ0YsS0FBSyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDbEIsV0FBVyxFQUFFLCtDQUErQztTQUM3RCxDQUFDO1FBQ0YsYUFBYSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDMUIsV0FBVyxFQUNULDJGQUEyRjtTQUM5RixDQUFDO1FBQ0YsS0FB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bGFncyB9IGZyb20gXCJAb2NsaWYvY29yZVwiO1xuaW1wb3J0IHsgQXV0aGVudGljYXRlZENvbW1hbmQgfSBmcm9tIFwiLi4vLi4vbGliL2Jhc2UtY29tbWFuZC5qc1wiO1xuaW1wb3J0IHsgYXBpQ2xpZW50IH0gZnJvbSBcIi4uLy4uL2xpYi9hcGktY2xpZW50LmpzXCI7XG5pbXBvcnQgeyBzdWNjZXNzLCBlcnJvciwgc3Bpbm5lciwganNvbiwgaXNKc29uTW9kZSB9IGZyb20gXCIuLi8uLi9saWIvb3V0cHV0LmpzXCI7XG5cbmludGVyZmFjZSBCYWNrZmlsbFJlc3BvbnNlIHtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBzeW50aGVzaXplZDogbnVtYmVyO1xuICBieV90eXBlOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+O1xuICB0cnVuY2F0ZWQ6IGJvb2xlYW47XG4gIGNhbmRpZGF0ZXNfc2Nhbm5lZDogbnVtYmVyO1xuICBkZWxpdmVyeV9pZHM6IHN0cmluZ1tdO1xuICBzaW5jZTogc3RyaW5nO1xuICB1bnRpbDogc3RyaW5nO1xuICBsaW1pdDogbnVtYmVyO1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWJob29rc0JhY2tmaWxsIGV4dGVuZHMgQXV0aGVudGljYXRlZENvbW1hbmQge1xuICBzdGF0aWMgZGVzY3JpcHRpb24gPVxuICAgIFwiU3ludGhlc2l6ZSBtaXNzZWQgd2ViaG9vayBldmVudHMgZnJvbSB0aGUgbWVzc2FnZSBsb2cuIFVzZSB3aGVuIGFuIG91dGFnZSBsZWZ0IGV2ZW50cyB3aXRoIG5vIGF1ZGl0IHJvdy5cIjtcblxuICBzdGF0aWMgZXhhbXBsZXMgPSBbXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiB3ZWJob29rcyBiYWNrZmlsbCB3aGtfYWJjMTIzXCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiB3ZWJob29rcyBiYWNrZmlsbCB3aGtfYWJjMTIzIC0tc2luY2UgMjAyNi0wNS0wMVQwMDowMDowMFogLS1saW1pdCA1MDAwXCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiB3ZWJob29rcyBiYWNrZmlsbCB3aGtfYWJjMTIzIC0tZXZlbnQtdHlwZXMgbWVzc2FnZS5kZWxpdmVyZWQsbWVzc2FnZS5mYWlsZWRcIixcbiAgXTtcblxuICBzdGF0aWMgYXJncyA9IHtcbiAgICBpZDogQXJncy5zdHJpbmcoeyBkZXNjcmlwdGlvbjogXCJXZWJob29rIElEXCIsIHJlcXVpcmVkOiB0cnVlIH0pLFxuICB9O1xuXG4gIHN0YXRpYyBmbGFncyA9IHtcbiAgICAuLi5BdXRoZW50aWNhdGVkQ29tbWFuZC5iYXNlRmxhZ3MsXG4gICAgc2luY2U6IEZsYWdzLnN0cmluZyh7XG4gICAgICBkZXNjcmlwdGlvbjogXCJFYXJsaWVzdCBtZXNzYWdlIHRpbWUgKElTTy04NjAxKS4gRGVmYXVsdDogbm93IOKIkiAyNGguXCIsXG4gICAgfSksXG4gICAgdW50aWw6IEZsYWdzLnN0cmluZyh7XG4gICAgICBkZXNjcmlwdGlvbjogXCJMYXRlc3QgbWVzc2FnZSB0aW1lIChJU08tODYwMSkuIERlZmF1bHQ6IG5vdy5cIixcbiAgICB9KSxcbiAgICBcImV2ZW50LXR5cGVzXCI6IEZsYWdzLnN0cmluZyh7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJDb21tYS1zZXBhcmF0ZWQgZXZlbnQgdHlwZXMgdG8gYmFja2ZpbGwgKG1lc3NhZ2Uuc2VudCwgbWVzc2FnZS5kZWxpdmVyZWQsIG1lc3NhZ2UuZmFpbGVkKVwiLFxuICAgIH0pLFxuICAgIGxpbWl0OiBGbGFncy5pbnRlZ2VyKHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIk1heGltdW0gZXZlbnRzIHRvIHN5bnRoZXNpemUgKG1heCAxMDAwMClcIixcbiAgICAgIGRlZmF1bHQ6IDEwMDAsXG4gICAgfSksXG4gIH07XG5cbiAgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgYXJncywgZmxhZ3MgfSA9IGF3YWl0IHRoaXMucGFyc2UoV2ViaG9va3NCYWNrZmlsbCk7XG5cbiAgICBjb25zdCBib2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICAgIGlmIChmbGFncy5zaW5jZSkgYm9keS5zaW5jZSA9IGZsYWdzLnNpbmNlO1xuICAgIGlmIChmbGFncy51bnRpbCkgYm9keS51bnRpbCA9IGZsYWdzLnVudGlsO1xuICAgIGlmIChmbGFnc1tcImV2ZW50LXR5cGVzXCJdKVxuICAgICAgYm9keS5ldmVudF90eXBlcyA9IGZsYWdzW1wiZXZlbnQtdHlwZXNcIl1cbiAgICAgICAgLnNwbGl0KFwiLFwiKVxuICAgICAgICAubWFwKChzKSA9PiBzLnRyaW0oKSlcbiAgICAgICAgLmZpbHRlcihCb29sZWFuKTtcbiAgICBpZiAoZmxhZ3MubGltaXQgIT09IHVuZGVmaW5lZCkgYm9keS5saW1pdCA9IGZsYWdzLmxpbWl0O1xuXG4gICAgY29uc3Qgc3AgPSBzcGlubmVyKFwiU3ludGhlc2l6aW5nIG1pc3NlZCBkZWxpdmVyaWVzLi4uXCIpO1xuICAgIHNwLnN0YXJ0KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYXBpQ2xpZW50LnBvc3Q8QmFja2ZpbGxSZXNwb25zZT4oXG4gICAgICAgIGAvYXBpL3YxL3dlYmhvb2tzLyR7YXJncy5pZH0vYmFja2ZpbGxgLFxuICAgICAgICBib2R5LFxuICAgICAgKTtcblxuICAgICAgc3Auc3RvcCgpO1xuXG4gICAgICBpZiAoaXNKc29uTW9kZSgpKSB7XG4gICAgICAgIGpzb24ocmVzdWx0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBieVR5cGUgPSBPYmplY3QuZW50cmllcyhyZXN1bHQuYnlfdHlwZSA/PyB7fSlcbiAgICAgICAgLm1hcCgoW2ssIHZdKSA9PiBgJHtrfT0ke3Z9YClcbiAgICAgICAgLmpvaW4oXCIsIFwiKTtcblxuICAgICAgc3VjY2VzcyhyZXN1bHQubWVzc2FnZSB8fCBcIkJhY2tmaWxsIGNvbXBsZXRlXCIsIHtcbiAgICAgICAgU3ludGhlc2l6ZWQ6IFN0cmluZyhyZXN1bHQuc3ludGhlc2l6ZWQpLFxuICAgICAgICBcIkJ5IFR5cGVcIjogYnlUeXBlIHx8IFwiKG5vbmUpXCIsXG4gICAgICAgIFwiQ2FuZGlkYXRlcyBTY2FubmVkXCI6IFN0cmluZyhyZXN1bHQuY2FuZGlkYXRlc19zY2FubmVkKSxcbiAgICAgICAgVHJ1bmNhdGVkOiByZXN1bHQudHJ1bmNhdGVkID8gXCJ5ZXMgKG1vcmUgZWxpZ2libGUgdGhhbiBsaW1pdClcIiA6IFwibm9cIixcbiAgICAgICAgV2luZG93OiBgJHtyZXN1bHQuc2luY2V9IOKGkiAke3Jlc3VsdC51bnRpbH1gLFxuICAgICAgICBMaW1pdDogU3RyaW5nKHJlc3VsdC5saW1pdCksXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHNwLnN0b3AoKTtcbiAgICAgIGVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGJhY2tmaWxsOiAke2VyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKX1gLFxuICAgICAgKTtcbiAgICAgIHRoaXMuZXhpdCgxKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,18 @@
1
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
2
+ export default class WebhooksRedeliver extends AuthenticatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ since: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ until: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ "event-types": import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ statuses: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
+ limit: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
+ json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,78 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
3
+ import { apiClient } from "../../lib/api-client.js";
4
+ import { success, error, spinner, json, isJsonMode } from "../../lib/output.js";
5
+ export default class WebhooksRedeliver extends AuthenticatedCommand {
6
+ static description = "Replay failed or cancelled webhook deliveries from the audit log. Reset the circuit first if it's open.";
7
+ static examples = [
8
+ "<%= config.bin %> webhooks redeliver whk_abc123",
9
+ "<%= config.bin %> webhooks redeliver whk_abc123 --since 2026-05-01T00:00:00Z --limit 5000",
10
+ "<%= config.bin %> webhooks redeliver whk_abc123 --event-types message.delivered,message.failed",
11
+ ];
12
+ static args = {
13
+ id: Args.string({ description: "Webhook ID", required: true }),
14
+ };
15
+ static flags = {
16
+ ...AuthenticatedCommand.baseFlags,
17
+ since: Flags.string({
18
+ description: "Earliest delivery time (ISO-8601). Default: now − 24h.",
19
+ }),
20
+ until: Flags.string({
21
+ description: "Latest delivery time (ISO-8601). Default: now.",
22
+ }),
23
+ "event-types": Flags.string({
24
+ description: "Comma-separated event types to filter on",
25
+ }),
26
+ statuses: Flags.string({
27
+ description: "Comma-separated delivery statuses to replay. Default: failed,cancelled",
28
+ }),
29
+ limit: Flags.integer({
30
+ description: "Maximum deliveries to requeue (max 10000)",
31
+ default: 1000,
32
+ }),
33
+ };
34
+ async run() {
35
+ const { args, flags } = await this.parse(WebhooksRedeliver);
36
+ const body = {};
37
+ if (flags.since)
38
+ body.since = flags.since;
39
+ if (flags.until)
40
+ body.until = flags.until;
41
+ if (flags["event-types"])
42
+ body.event_types = flags["event-types"]
43
+ .split(",")
44
+ .map((s) => s.trim())
45
+ .filter(Boolean);
46
+ if (flags.statuses)
47
+ body.statuses = flags.statuses
48
+ .split(",")
49
+ .map((s) => s.trim())
50
+ .filter(Boolean);
51
+ if (flags.limit !== undefined)
52
+ body.limit = flags.limit;
53
+ const sp = spinner("Requeuing deliveries...");
54
+ sp.start();
55
+ try {
56
+ const result = await apiClient.post(`/api/v1/webhooks/${args.id}/redeliver`, body);
57
+ sp.stop();
58
+ if (isJsonMode()) {
59
+ json(result);
60
+ return;
61
+ }
62
+ success(result.message || "Redeliver complete", {
63
+ Requeued: String(result.requeued),
64
+ Skipped: String(result.skipped),
65
+ Truncated: result.truncated ? "yes (window larger than limit)" : "no",
66
+ "Window Size": String(result.window_size),
67
+ Window: `${result.since} → ${result.until}`,
68
+ Limit: String(result.limit),
69
+ });
70
+ }
71
+ catch (err) {
72
+ sp.stop();
73
+ error(`Failed to redeliver: ${err instanceof Error ? err.message : String(err)}`);
74
+ this.exit(1);
75
+ }
76
+ }
77
+ }
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkZWxpdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL3dlYmhvb2tzL3JlZGVsaXZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMxQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQWNoRixNQUFNLENBQUMsT0FBTyxPQUFPLGlCQUFrQixTQUFRLG9CQUFvQjtJQUNqRSxNQUFNLENBQUMsV0FBVyxHQUNoQix5R0FBeUcsQ0FBQztJQUU1RyxNQUFNLENBQUMsUUFBUSxHQUFHO1FBQ2hCLGlEQUFpRDtRQUNqRCwyRkFBMkY7UUFDM0YsZ0dBQWdHO0tBQ2pHLENBQUM7SUFFRixNQUFNLENBQUMsSUFBSSxHQUFHO1FBQ1osRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQztLQUMvRCxDQUFDO0lBRUYsTUFBTSxDQUFDLEtBQUssR0FBRztRQUNiLEdBQUcsb0JBQW9CLENBQUMsU0FBUztRQUNqQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUNsQixXQUFXLEVBQUUsd0RBQXdEO1NBQ3RFLENBQUM7UUFDRixLQUFLLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUNsQixXQUFXLEVBQUUsZ0RBQWdEO1NBQzlELENBQUM7UUFDRixhQUFhLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUMxQixXQUFXLEVBQUUsMENBQTBDO1NBQ3hELENBQUM7UUFDRixR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QUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFyZ3MsIEZsYWdzIH0gZnJvbSBcIkBvY2xpZi9jb3JlXCI7XG5pbXBvcnQgeyBBdXRoZW50aWNhdGVkQ29tbWFuZCB9IGZyb20gXCIuLi8uLi9saWIvYmFzZS1jb21tYW5kLmpzXCI7XG5pbXBvcnQgeyBhcGlDbGllbnQgfSBmcm9tIFwiLi4vLi4vbGliL2FwaS1jbGllbnQuanNcIjtcbmltcG9ydCB7IHN1Y2Nlc3MsIGVycm9yLCBzcGlubmVyLCBqc29uLCBpc0pzb25Nb2RlIH0gZnJvbSBcIi4uLy4uL2xpYi9vdXRwdXQuanNcIjtcblxuaW50ZXJmYWNlIFJlZGVsaXZlclJlc3BvbnNlIHtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICByZXF1ZXVlZDogbnVtYmVyO1xuICBza2lwcGVkOiBudW1iZXI7XG4gIHRydW5jYXRlZDogYm9vbGVhbjtcbiAgd2luZG93X3NpemU6IG51bWJlcjtcbiAgZGVsaXZlcnlfaWRzOiBzdHJpbmdbXTtcbiAgc2luY2U6IHN0cmluZztcbiAgdW50aWw6IHN0cmluZztcbiAgbGltaXQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViaG9va3NSZWRlbGl2ZXIgZXh0ZW5kcyBBdXRoZW50aWNhdGVkQ29tbWFuZCB7XG4gIHN0YXRpYyBkZXNjcmlwdGlvbiA9XG4gICAgXCJSZXBsYXkgZmFpbGVkIG9yIGNhbmNlbGxlZCB3ZWJob29rIGRlbGl2ZXJpZXMgZnJvbSB0aGUgYXVkaXQgbG9nLiBSZXNldCB0aGUgY2lyY3VpdCBmaXJzdCBpZiBpdCdzIG9wZW4uXCI7XG5cbiAgc3RhdGljIGV4YW1wbGVzID0gW1xuICAgIFwiPCU9IGNvbmZpZy5iaW4gJT4gd2ViaG9va3MgcmVkZWxpdmVyIHdoa19hYmMxMjNcIixcbiAgICBcIjwlPSBjb25maWcuYmluICU+IHdlYmhvb2tzIHJlZGVsaXZlciB3aGtfYWJjMTIzIC0tc2luY2UgMjAyNi0wNS0wMVQwMDowMDowMFogLS1saW1pdCA1MDAwXCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiB3ZWJob29rcyByZWRlbGl2ZXIgd2hrX2FiYzEyMyAtLWV2ZW50LXR5cGVzIG1lc3NhZ2UuZGVsaXZlcmVkLG1lc3NhZ2UuZmFpbGVkXCIsXG4gIF07XG5cbiAgc3RhdGljIGFyZ3MgPSB7XG4gICAgaWQ6IEFyZ3Muc3RyaW5nKHsgZGVzY3JpcHRpb246IFwiV2ViaG9vayBJRFwiLCByZXF1aXJlZDogdHJ1ZSB9KSxcbiAgfTtcblxuICBzdGF0aWMgZmxhZ3MgPSB7XG4gICAgLi4uQXV0aGVudGljYXRlZENvbW1hbmQuYmFzZUZsYWdzLFxuICAgIHNpbmNlOiBGbGFncy5zdHJpbmcoe1xuICAgICAgZGVzY3JpcHRpb246IFwiRWFybGllc3QgZGVsaXZlcnkgdGltZSAoSVNPLTg2MDEpLiBEZWZhdWx0OiBub3cg4oiSIDI0aC5cIixcbiAgICB9KSxcbiAgICB1bnRpbDogRmxhZ3Muc3RyaW5nKHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkxhdGVzdCBkZWxpdmVyeSB0aW1lIChJU08tODYwMSkuIERlZmF1bHQ6IG5vdy5cIixcbiAgICB9KSxcbiAgICBcImV2ZW50LXR5cGVzXCI6IEZsYWdzLnN0cmluZyh7XG4gICAgICBkZXNjcmlwdGlvbjogXCJDb21tYS1zZXBhcmF0ZWQgZXZlbnQgdHlwZXMgdG8gZmlsdGVyIG9uXCIsXG4gICAgfSksXG4gICAgc3RhdHVzZXM6IEZsYWdzLnN0cmluZyh7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJDb21tYS1zZXBhcmF0ZWQgZGVsaXZlcnkgc3RhdHVzZXMgdG8gcmVwbGF5LiBEZWZhdWx0OiBmYWlsZWQsY2FuY2VsbGVkXCIsXG4gICAgfSksXG4gICAgbGltaXQ6IEZsYWdzLmludGVnZXIoe1xuICAgICAgZGVzY3JpcHRpb246IFwiTWF4aW11bSBkZWxpdmVyaWVzIHRvIHJlcXVldWUgKG1heCAxMDAwMClcIixcbiAgICAgIGRlZmF1bHQ6IDEwMDAsXG4gICAgfSksXG4gIH07XG5cbiAgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgYXJncywgZmxhZ3MgfSA9IGF3YWl0IHRoaXMucGFyc2UoV2ViaG9va3NSZWRlbGl2ZXIpO1xuXG4gICAgY29uc3QgYm9keTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBpZiAoZmxhZ3Muc2luY2UpIGJvZHkuc2luY2UgPSBmbGFncy5zaW5jZTtcbiAgICBpZiAoZmxhZ3MudW50aWwpIGJvZHkudW50aWwgPSBmbGFncy51bnRpbDtcbiAgICBpZiAoZmxhZ3NbXCJldmVudC10eXBlc1wiXSlcbiAgICAgIGJvZHkuZXZlbnRfdHlwZXMgPSBmbGFnc1tcImV2ZW50LXR5cGVzXCJdXG4gICAgICAgIC5zcGxpdChcIixcIilcbiAgICAgICAgLm1hcCgocykgPT4gcy50cmltKCkpXG4gICAgICAgIC5maWx0ZXIoQm9vbGVhbik7XG4gICAgaWYgKGZsYWdzLnN0YXR1c2VzKVxuICAgICAgYm9keS5zdGF0dXNlcyA9IGZsYWdzLnN0YXR1c2VzXG4gICAgICAgIC5zcGxpdChcIixcIilcbiAgICAgICAgLm1hcCgocykgPT4gcy50cmltKCkpXG4gICAgICAgIC5maWx0ZXIoQm9vbGVhbik7XG4gICAgaWYgKGZsYWdzLmxpbWl0ICE9PSB1bmRlZmluZWQpIGJvZHkubGltaXQgPSBmbGFncy5saW1pdDtcblxuICAgIGNvbnN0IHNwID0gc3Bpbm5lcihcIlJlcXVldWluZyBkZWxpdmVyaWVzLi4uXCIpO1xuICAgIHNwLnN0YXJ0KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYXBpQ2xpZW50LnBvc3Q8UmVkZWxpdmVyUmVzcG9uc2U+KFxuICAgICAgICBgL2FwaS92MS93ZWJob29rcy8ke2FyZ3MuaWR9L3JlZGVsaXZlcmAsXG4gICAgICAgIGJvZHksXG4gICAgICApO1xuXG4gICAgICBzcC5zdG9wKCk7XG5cbiAgICAgIGlmIChpc0pzb25Nb2RlKCkpIHtcbiAgICAgICAganNvbihyZXN1bHQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHN1Y2Nlc3MocmVzdWx0Lm1lc3NhZ2UgfHwgXCJSZWRlbGl2ZXIgY29tcGxldGVcIiwge1xuICAgICAgICBSZXF1ZXVlZDogU3RyaW5nKHJlc3VsdC5yZXF1ZXVlZCksXG4gICAgICAgIFNraXBwZWQ6IFN0cmluZyhyZXN1bHQuc2tpcHBlZCksXG4gICAgICAgIFRydW5jYXRlZDogcmVzdWx0LnRydW5jYXRlZCA/IFwieWVzICh3aW5kb3cgbGFyZ2VyIHRoYW4gbGltaXQpXCIgOiBcIm5vXCIsXG4gICAgICAgIFwiV2luZG93IFNpemVcIjogU3RyaW5nKHJlc3VsdC53aW5kb3dfc2l6ZSksXG4gICAgICAgIFdpbmRvdzogYCR7cmVzdWx0LnNpbmNlfSDihpIgJHtyZXN1bHQudW50aWx9YCxcbiAgICAgICAgTGltaXQ6IFN0cmluZyhyZXN1bHQubGltaXQpLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBzcC5zdG9wKCk7XG4gICAgICBlcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byByZWRlbGl2ZXI6ICR7ZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpfWAsXG4gICAgICApO1xuICAgICAgdGhpcy5leGl0KDEpO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,13 @@
1
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
2
+ export default class WebhooksResetCircuit extends AuthenticatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
10
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,44 @@
1
+ import { Args } from "@oclif/core";
2
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
3
+ import { apiClient } from "../../lib/api-client.js";
4
+ import { success, error, spinner, json, isJsonMode } from "../../lib/output.js";
5
+ export default class WebhooksResetCircuit extends AuthenticatedCommand {
6
+ static description = "Reset the circuit breaker for a webhook";
7
+ static examples = [
8
+ "<%= config.bin %> webhooks reset-circuit whk_abc123",
9
+ "<%= config.bin %> webhooks reset-circuit whk_abc123 --json",
10
+ ];
11
+ static args = {
12
+ id: Args.string({
13
+ description: "Webhook ID",
14
+ required: true,
15
+ }),
16
+ };
17
+ static flags = {
18
+ ...AuthenticatedCommand.baseFlags,
19
+ };
20
+ async run() {
21
+ const { args } = await this.parse(WebhooksResetCircuit);
22
+ const sp = spinner("Resetting circuit breaker...");
23
+ sp.start();
24
+ try {
25
+ const result = await apiClient.post(`/api/v1/webhooks/${args.id}/reset-circuit`);
26
+ sp.stop();
27
+ if (isJsonMode()) {
28
+ json(result);
29
+ return;
30
+ }
31
+ success(result.message || "Circuit breaker reset", {
32
+ "Webhook ID": result.webhook?.id || args.id,
33
+ "Circuit State": result.webhook?.circuit_state || "closed",
34
+ "Failure Count": String(result.webhook?.failure_count ?? 0),
35
+ });
36
+ }
37
+ catch (err) {
38
+ sp.stop();
39
+ error(`Failed to reset circuit: ${err instanceof Error ? err.message : String(err)}`);
40
+ this.exit(1);
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzZXQtY2lyY3VpdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy93ZWJob29rcy9yZXNldC1jaXJjdWl0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbkMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFPaEYsTUFBTSxDQUFDLE9BQU8sT0FBTyxvQkFBcUIsU0FBUSxvQkFBb0I7SUFDcEUsTUFBTSxDQUFDLFdBQVcsR0FBRyx5Q0FBeUMsQ0FBQztJQUUvRCxNQUFNLENBQUMsUUFBUSxHQUFHO1FBQ2hCLHFEQUFxRDtRQUNyRCw0REFBNEQ7S0FDN0QsQ0FBQztJQUVGLE1BQU0sQ0FBQyxJQUFJLEdBQUc7UUFDWixFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQztZQUNkLFdBQVcsRUFBRSxZQUFZO1lBQ3pCLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQztLQUNILENBQUM7SUFFRixNQUFNLENBQUMsS0FBSyxHQUFHO1FBQ2IsR0FBRyxvQkFBb0IsQ0FBQyxTQUFTO0tBQ2xDLENBQUM7SUFFRixLQUFLLENBQUMsR0FBRztRQUNQLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUV4RCxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUNuRCxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFWCxJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxJQUFJLENBQ2pDLG9CQUFvQixJQUFJLENBQUMsRUFBRSxnQkFBZ0IsQ0FDNUMsQ0FBQztZQUVGLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUVWLElBQUksVUFBVSxFQUFFLEVBQUUsQ0FBQztnQkFDakIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNiLE9BQU87WUFDVCxDQUFDO1lBRUQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksdUJBQXVCLEVBQUU7Z0JBQ2pELFlBQVksRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxJQUFJLENBQUMsRUFBRTtnQkFDM0MsZUFBZSxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsYUFBYSxJQUFJLFFBQVE7Z0JBQzFELGVBQWUsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxhQUFhLElBQUksQ0FBQyxDQUFDO2FBQzVELENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsS0FBSyxDQUNILDRCQUE0QixHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FDL0UsQ0FBQztZQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFyZ3MgfSBmcm9tIFwiQG9jbGlmL2NvcmVcIjtcbmltcG9ydCB7IEF1dGhlbnRpY2F0ZWRDb21tYW5kIH0gZnJvbSBcIi4uLy4uL2xpYi9iYXNlLWNvbW1hbmQuanNcIjtcbmltcG9ydCB7IGFwaUNsaWVudCB9IGZyb20gXCIuLi8uLi9saWIvYXBpLWNsaWVudC5qc1wiO1xuaW1wb3J0IHsgc3VjY2VzcywgZXJyb3IsIHNwaW5uZXIsIGpzb24sIGlzSnNvbk1vZGUgfSBmcm9tIFwiLi4vLi4vbGliL291dHB1dC5qc1wiO1xuXG5pbnRlcmZhY2UgUmVzZXRDaXJjdWl0UmVzcG9uc2Uge1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIHdlYmhvb2s/OiB7IGlkOiBzdHJpbmc7IGNpcmN1aXRfc3RhdGU/OiBzdHJpbmc7IGZhaWx1cmVfY291bnQ/OiBudW1iZXIgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViaG9va3NSZXNldENpcmN1aXQgZXh0ZW5kcyBBdXRoZW50aWNhdGVkQ29tbWFuZCB7XG4gIHN0YXRpYyBkZXNjcmlwdGlvbiA9IFwiUmVzZXQgdGhlIGNpcmN1aXQgYnJlYWtlciBmb3IgYSB3ZWJob29rXCI7XG5cbiAgc3RhdGljIGV4YW1wbGVzID0gW1xuICAgIFwiPCU9IGNvbmZpZy5iaW4gJT4gd2ViaG9va3MgcmVzZXQtY2lyY3VpdCB3aGtfYWJjMTIzXCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiB3ZWJob29rcyByZXNldC1jaXJjdWl0IHdoa19hYmMxMjMgLS1qc29uXCIsXG4gIF07XG5cbiAgc3RhdGljIGFyZ3MgPSB7XG4gICAgaWQ6IEFyZ3Muc3RyaW5nKHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIldlYmhvb2sgSURcIixcbiAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIH0pLFxuICB9O1xuXG4gIHN0YXRpYyBmbGFncyA9IHtcbiAgICAuLi5BdXRoZW50aWNhdGVkQ29tbWFuZC5iYXNlRmxhZ3MsXG4gIH07XG5cbiAgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgYXJncyB9ID0gYXdhaXQgdGhpcy5wYXJzZShXZWJob29rc1Jlc2V0Q2lyY3VpdCk7XG5cbiAgICBjb25zdCBzcCA9IHNwaW5uZXIoXCJSZXNldHRpbmcgY2lyY3VpdCBicmVha2VyLi4uXCIpO1xuICAgIHNwLnN0YXJ0KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYXBpQ2xpZW50LnBvc3Q8UmVzZXRDaXJjdWl0UmVzcG9uc2U+KFxuICAgICAgICBgL2FwaS92MS93ZWJob29rcy8ke2FyZ3MuaWR9L3Jlc2V0LWNpcmN1aXRgLFxuICAgICAgKTtcblxuICAgICAgc3Auc3RvcCgpO1xuXG4gICAgICBpZiAoaXNKc29uTW9kZSgpKSB7XG4gICAgICAgIGpzb24ocmVzdWx0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzdWNjZXNzKHJlc3VsdC5tZXNzYWdlIHx8IFwiQ2lyY3VpdCBicmVha2VyIHJlc2V0XCIsIHtcbiAgICAgICAgXCJXZWJob29rIElEXCI6IHJlc3VsdC53ZWJob29rPy5pZCB8fCBhcmdzLmlkLFxuICAgICAgICBcIkNpcmN1aXQgU3RhdGVcIjogcmVzdWx0LndlYmhvb2s/LmNpcmN1aXRfc3RhdGUgfHwgXCJjbG9zZWRcIixcbiAgICAgICAgXCJGYWlsdXJlIENvdW50XCI6IFN0cmluZyhyZXN1bHQud2ViaG9vaz8uZmFpbHVyZV9jb3VudCA/PyAwKSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgc3Auc3RvcCgpO1xuICAgICAgZXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmVzZXQgY2lyY3VpdDogJHtlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycil9YCxcbiAgICAgICk7XG4gICAgICB0aGlzLmV4aXQoMSk7XG4gICAgfVxuICB9XG59XG4iXX0=