@hogsend/cli 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +441 -4
- package/dist/bin.js.map +1 -1
- package/package.json +2 -2
- package/skills/hogsend-authoring-destinations/SKILL.md +217 -0
- package/skills/hogsend-authoring-emails/references/tracking-and-unsubscribe.md +7 -2
- package/skills/hogsend-authoring-journeys/SKILL.md +11 -4
- package/skills/hogsend-authoring-journeys/references/journey-context.md +22 -8
- package/skills/hogsend-cli/SKILL.md +1 -0
- package/skills/hogsend-client-sdk/SKILL.md +58 -1
- package/skills/hogsend-client-sdk/references/api-surface.md +108 -0
- package/skills/hogsend-extending/SKILL.md +42 -11
- package/skills/hogsend-extending/references/swap-a-provider.md +15 -2
- package/skills/hogsend-webhooks-and-workflows/SKILL.md +32 -5
- package/skills/hogsend-webhooks-and-workflows/references/webhook-source.md +57 -12
- package/src/commands/index.ts +2 -0
- package/src/commands/webhooks.ts +566 -0
- package/src/lib/http.ts +6 -0
package/dist/bin.js
CHANGED
|
@@ -85,6 +85,10 @@ function createAdminClient(cfg) {
|
|
|
85
85
|
post: (path, body) => request(cfg.baseUrl, cfg.adminKey, missing, "POST", path, {
|
|
86
86
|
body,
|
|
87
87
|
auth: true
|
|
88
|
+
}),
|
|
89
|
+
del: (path, body) => request(cfg.baseUrl, cfg.adminKey, missing, "DELETE", path, {
|
|
90
|
+
body,
|
|
91
|
+
auth: true
|
|
88
92
|
})
|
|
89
93
|
};
|
|
90
94
|
}
|
|
@@ -1057,8 +1061,8 @@ async function run3(ctx) {
|
|
|
1057
1061
|
if (!ok) process.exit(1);
|
|
1058
1062
|
return;
|
|
1059
1063
|
}
|
|
1060
|
-
const
|
|
1061
|
-
ctx.out.intro(
|
|
1064
|
+
const badge6 = `${color.bgMagenta(color.black(" hogsend "))} doctor`;
|
|
1065
|
+
ctx.out.intro(badge6);
|
|
1062
1066
|
const verdictColor = verdict === "ok" ? color.green : verdict === "degraded" ? color.red : color.yellow;
|
|
1063
1067
|
const lines = [
|
|
1064
1068
|
`${verdictColor("\u25CF")} ${color.bold(verdict)}`,
|
|
@@ -2944,6 +2948,438 @@ var upgradeCommand = {
|
|
|
2944
2948
|
run: run13
|
|
2945
2949
|
};
|
|
2946
2950
|
|
|
2951
|
+
// src/commands/webhooks.ts
|
|
2952
|
+
import { parseArgs as parseArgs14 } from "util";
|
|
2953
|
+
var WEBHOOK_EVENT_TYPES = [
|
|
2954
|
+
"contact.created",
|
|
2955
|
+
"contact.updated",
|
|
2956
|
+
"contact.deleted",
|
|
2957
|
+
"contact.unsubscribed",
|
|
2958
|
+
"email.sent",
|
|
2959
|
+
"email.delivered",
|
|
2960
|
+
"email.opened",
|
|
2961
|
+
"email.clicked",
|
|
2962
|
+
"email.bounced",
|
|
2963
|
+
"email.complained",
|
|
2964
|
+
"journey.completed",
|
|
2965
|
+
"bucket.entered",
|
|
2966
|
+
"bucket.left"
|
|
2967
|
+
];
|
|
2968
|
+
var usage14 = `hogsend webhooks <subcommand> [options]
|
|
2969
|
+
|
|
2970
|
+
Manage outbound webhook endpoints \u2014 the Svix-style signed event stream Hogsend
|
|
2971
|
+
emits to your URLs. Wraps the admin routes (/v1/admin/webhooks), so this command
|
|
2972
|
+
REQUIRES an admin key (--admin-key / HOGSEND_ADMIN_KEY), not the data key.
|
|
2973
|
+
|
|
2974
|
+
Subcommands:
|
|
2975
|
+
list List endpoints.
|
|
2976
|
+
get <id> Show one endpoint.
|
|
2977
|
+
create Register an endpoint (prints the secret ONCE).
|
|
2978
|
+
update <id> Patch an endpoint.
|
|
2979
|
+
delete <id> Hard-delete an endpoint (drops its deliveries).
|
|
2980
|
+
rotate-secret <id> Issue a new signing secret (prints it ONCE).
|
|
2981
|
+
test <id> Enqueue an out-of-band webhook.test delivery.
|
|
2982
|
+
|
|
2983
|
+
list options:
|
|
2984
|
+
--include-disabled Include disabled endpoints.
|
|
2985
|
+
--limit <n> Page size.
|
|
2986
|
+
--offset <n> Page offset.
|
|
2987
|
+
|
|
2988
|
+
create options (--url required, plus at least one event):
|
|
2989
|
+
--url <url> Destination URL (required).
|
|
2990
|
+
--event <type> Subscribe to an event; repeatable.
|
|
2991
|
+
--all-events Subscribe to all 13 event types.
|
|
2992
|
+
--description <text> Human label.
|
|
2993
|
+
--disabled Create the endpoint disabled.
|
|
2994
|
+
|
|
2995
|
+
update options (only the provided fields change):
|
|
2996
|
+
--url <url> New destination URL.
|
|
2997
|
+
--event <type> Replace the subscribed events (repeatable).
|
|
2998
|
+
--all-events Subscribe to all 13 event types.
|
|
2999
|
+
--description <text> New description.
|
|
3000
|
+
--disabled / --enabled Disable or enable the endpoint.
|
|
3001
|
+
|
|
3002
|
+
Event types:
|
|
3003
|
+
${WEBHOOK_EVENT_TYPES.join(", ")}
|
|
3004
|
+
|
|
3005
|
+
Global options (handled by the router): --url, --admin-key, --data-key, --json,
|
|
3006
|
+
-h/--help.
|
|
3007
|
+
|
|
3008
|
+
Examples:
|
|
3009
|
+
hogsend webhooks create --url https://x.com/hook --event contact.created --event email.sent
|
|
3010
|
+
hogsend webhooks create --url https://x.com/hook --all-events --json
|
|
3011
|
+
hogsend webhooks list --include-disabled
|
|
3012
|
+
hogsend webhooks rotate-secret we_123
|
|
3013
|
+
hogsend webhooks test we_123`;
|
|
3014
|
+
var badge5 = `${color.bgMagenta(color.black(" hogsend "))} webhooks`;
|
|
3015
|
+
async function fetchOrFail2(ctx, label, fn) {
|
|
3016
|
+
try {
|
|
3017
|
+
return await ctx.out.step(label, fn);
|
|
3018
|
+
} catch (err) {
|
|
3019
|
+
if (isHttpError(err)) {
|
|
3020
|
+
if (err.status === 404) {
|
|
3021
|
+
ctx.out.fail(err.message || "webhook endpoint not found");
|
|
3022
|
+
}
|
|
3023
|
+
ctx.out.fail(err.message);
|
|
3024
|
+
}
|
|
3025
|
+
throw err;
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
function resolveEvents(ctx, allEvents, events) {
|
|
3029
|
+
if (allEvents) {
|
|
3030
|
+
return [...WEBHOOK_EVENT_TYPES];
|
|
3031
|
+
}
|
|
3032
|
+
if (!events || events.length === 0) {
|
|
3033
|
+
return void 0;
|
|
3034
|
+
}
|
|
3035
|
+
const valid = new Set(WEBHOOK_EVENT_TYPES);
|
|
3036
|
+
const out = [];
|
|
3037
|
+
for (const ev of events) {
|
|
3038
|
+
if (!valid.has(ev)) {
|
|
3039
|
+
ctx.out.fail(
|
|
3040
|
+
`unknown event type "${ev}" \u2014 expected one of: ${WEBHOOK_EVENT_TYPES.join(", ")}`
|
|
3041
|
+
);
|
|
3042
|
+
}
|
|
3043
|
+
if (!out.includes(ev)) {
|
|
3044
|
+
out.push(ev);
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
return out;
|
|
3048
|
+
}
|
|
3049
|
+
function printSecretOnce(ctx, secret) {
|
|
3050
|
+
ctx.out.note(
|
|
3051
|
+
`${color.yellow("Store this signing secret now \u2014 it is shown only once and cannot be recovered.")}
|
|
3052
|
+
|
|
3053
|
+
${color.bold(secret)}`,
|
|
3054
|
+
color.yellow("Signing secret")
|
|
3055
|
+
);
|
|
3056
|
+
}
|
|
3057
|
+
async function runList4(ctx, argv) {
|
|
3058
|
+
const { values } = parseArgs14({
|
|
3059
|
+
args: argv,
|
|
3060
|
+
allowPositionals: true,
|
|
3061
|
+
options: {
|
|
3062
|
+
"include-disabled": { type: "boolean", default: false },
|
|
3063
|
+
limit: { type: "string" },
|
|
3064
|
+
offset: { type: "string" },
|
|
3065
|
+
help: { type: "boolean", short: "h", default: false }
|
|
3066
|
+
}
|
|
3067
|
+
});
|
|
3068
|
+
if (values.help) {
|
|
3069
|
+
ctx.out.log(usage14);
|
|
3070
|
+
return;
|
|
3071
|
+
}
|
|
3072
|
+
const query = {
|
|
3073
|
+
includeDisabled: values["include-disabled"] ? "true" : void 0,
|
|
3074
|
+
limit: values.limit,
|
|
3075
|
+
offset: values.offset
|
|
3076
|
+
};
|
|
3077
|
+
if (!ctx.json) ctx.out.intro(`${badge5} list`);
|
|
3078
|
+
const res = await fetchOrFail2(
|
|
3079
|
+
ctx,
|
|
3080
|
+
"Fetching webhooks",
|
|
3081
|
+
() => ctx.http.get("/v1/admin/webhooks", query)
|
|
3082
|
+
);
|
|
3083
|
+
if (ctx.json) {
|
|
3084
|
+
ctx.out.json(res);
|
|
3085
|
+
return;
|
|
3086
|
+
}
|
|
3087
|
+
ctx.out.table(
|
|
3088
|
+
res.endpoints.map((ep) => ({
|
|
3089
|
+
id: ep.id,
|
|
3090
|
+
url: ep.url,
|
|
3091
|
+
status: ep.status === "enabled" ? color.green(ep.status) : color.yellow(ep.status),
|
|
3092
|
+
events: ep.eventTypes.length,
|
|
3093
|
+
lastDeliveryAt: ep.lastDeliveryAt ?? color.dim("(never)")
|
|
3094
|
+
})),
|
|
3095
|
+
["id", "url", "status", "events", "lastDeliveryAt"]
|
|
3096
|
+
);
|
|
3097
|
+
ctx.out.outro(
|
|
3098
|
+
`${res.endpoints.length} of ${res.total} endpoint(s) \u2014 offset ${res.offset}, limit ${res.limit}`
|
|
3099
|
+
);
|
|
3100
|
+
}
|
|
3101
|
+
function renderEndpoint(ctx, ep, title) {
|
|
3102
|
+
ctx.out.kv(
|
|
3103
|
+
{
|
|
3104
|
+
id: ep.id,
|
|
3105
|
+
url: ep.url,
|
|
3106
|
+
description: ep.description ?? color.dim("(none)"),
|
|
3107
|
+
status: ep.status === "enabled" ? color.green(ep.status) : color.yellow(ep.status),
|
|
3108
|
+
eventTypes: ep.eventTypes,
|
|
3109
|
+
secretPrefix: ep.secretPrefix ?? color.dim("(none \u2014 keyed destination)"),
|
|
3110
|
+
lastDeliveryAt: ep.lastDeliveryAt ?? color.dim("(never)"),
|
|
3111
|
+
createdAt: ep.createdAt,
|
|
3112
|
+
updatedAt: ep.updatedAt
|
|
3113
|
+
},
|
|
3114
|
+
title
|
|
3115
|
+
);
|
|
3116
|
+
}
|
|
3117
|
+
async function runGet3(ctx, argv) {
|
|
3118
|
+
const { values, positionals } = parseArgs14({
|
|
3119
|
+
args: argv,
|
|
3120
|
+
allowPositionals: true,
|
|
3121
|
+
options: { help: { type: "boolean", short: "h", default: false } }
|
|
3122
|
+
});
|
|
3123
|
+
if (values.help) {
|
|
3124
|
+
ctx.out.log(usage14);
|
|
3125
|
+
return;
|
|
3126
|
+
}
|
|
3127
|
+
const id = positionals[0];
|
|
3128
|
+
if (!id) {
|
|
3129
|
+
ctx.out.fail(
|
|
3130
|
+
"webhooks get requires an endpoint id, e.g. hogsend webhooks get we_123"
|
|
3131
|
+
);
|
|
3132
|
+
}
|
|
3133
|
+
if (!ctx.json) ctx.out.intro(`${badge5} get`);
|
|
3134
|
+
const res = await fetchOrFail2(
|
|
3135
|
+
ctx,
|
|
3136
|
+
"Fetching webhook",
|
|
3137
|
+
() => ctx.http.get(
|
|
3138
|
+
`/v1/admin/webhooks/${encodeURIComponent(id)}`
|
|
3139
|
+
)
|
|
3140
|
+
);
|
|
3141
|
+
if (ctx.json) {
|
|
3142
|
+
ctx.out.json(res);
|
|
3143
|
+
return;
|
|
3144
|
+
}
|
|
3145
|
+
renderEndpoint(ctx, res, "Endpoint");
|
|
3146
|
+
ctx.out.outro(`${res.url} \u2192 ${res.status}`);
|
|
3147
|
+
}
|
|
3148
|
+
async function runCreate(ctx, argv) {
|
|
3149
|
+
const { values } = parseArgs14({
|
|
3150
|
+
args: argv,
|
|
3151
|
+
allowPositionals: true,
|
|
3152
|
+
options: {
|
|
3153
|
+
url: { type: "string" },
|
|
3154
|
+
event: { type: "string", multiple: true },
|
|
3155
|
+
"all-events": { type: "boolean", default: false },
|
|
3156
|
+
description: { type: "string" },
|
|
3157
|
+
disabled: { type: "boolean", default: false },
|
|
3158
|
+
help: { type: "boolean", short: "h", default: false }
|
|
3159
|
+
}
|
|
3160
|
+
});
|
|
3161
|
+
if (values.help) {
|
|
3162
|
+
ctx.out.log(usage14);
|
|
3163
|
+
return;
|
|
3164
|
+
}
|
|
3165
|
+
const url = values.url;
|
|
3166
|
+
if (!url) {
|
|
3167
|
+
ctx.out.fail(
|
|
3168
|
+
"webhooks create requires --url, e.g. hogsend webhooks create --url https://x.com/hook --all-events"
|
|
3169
|
+
);
|
|
3170
|
+
}
|
|
3171
|
+
const eventTypes = resolveEvents(ctx, values["all-events"], values.event);
|
|
3172
|
+
if (!eventTypes || eventTypes.length === 0) {
|
|
3173
|
+
ctx.out.fail(
|
|
3174
|
+
"webhooks create requires at least one --event <type> (or --all-events)"
|
|
3175
|
+
);
|
|
3176
|
+
}
|
|
3177
|
+
const body = { url, eventTypes };
|
|
3178
|
+
if (values.description !== void 0) body.description = values.description;
|
|
3179
|
+
if (values.disabled) body.disabled = true;
|
|
3180
|
+
if (!ctx.json) ctx.out.intro(`${badge5} create`);
|
|
3181
|
+
const res = await fetchOrFail2(
|
|
3182
|
+
ctx,
|
|
3183
|
+
"Creating webhook",
|
|
3184
|
+
() => ctx.http.post("/v1/admin/webhooks", body)
|
|
3185
|
+
);
|
|
3186
|
+
if (ctx.json) {
|
|
3187
|
+
ctx.out.json(res);
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
const { secret, ...endpoint } = res;
|
|
3191
|
+
renderEndpoint(ctx, endpoint, "Endpoint created");
|
|
3192
|
+
printSecretOnce(ctx, secret);
|
|
3193
|
+
ctx.out.outro(`${color.green("Created")} ${res.id} \u2192 ${res.url}`);
|
|
3194
|
+
}
|
|
3195
|
+
async function runUpdate(ctx, argv) {
|
|
3196
|
+
const { values, positionals } = parseArgs14({
|
|
3197
|
+
args: argv,
|
|
3198
|
+
allowPositionals: true,
|
|
3199
|
+
options: {
|
|
3200
|
+
url: { type: "string" },
|
|
3201
|
+
event: { type: "string", multiple: true },
|
|
3202
|
+
"all-events": { type: "boolean", default: false },
|
|
3203
|
+
description: { type: "string" },
|
|
3204
|
+
disabled: { type: "boolean", default: false },
|
|
3205
|
+
enabled: { type: "boolean", default: false },
|
|
3206
|
+
help: { type: "boolean", short: "h", default: false }
|
|
3207
|
+
}
|
|
3208
|
+
});
|
|
3209
|
+
if (values.help) {
|
|
3210
|
+
ctx.out.log(usage14);
|
|
3211
|
+
return;
|
|
3212
|
+
}
|
|
3213
|
+
const id = positionals[0];
|
|
3214
|
+
if (!id) {
|
|
3215
|
+
ctx.out.fail(
|
|
3216
|
+
"webhooks update requires an endpoint id, e.g. hogsend webhooks update we_123 --enabled"
|
|
3217
|
+
);
|
|
3218
|
+
}
|
|
3219
|
+
if (values.disabled && values.enabled) {
|
|
3220
|
+
ctx.out.fail("webhooks update: pass at most one of --disabled / --enabled");
|
|
3221
|
+
}
|
|
3222
|
+
const eventTypes = resolveEvents(ctx, values["all-events"], values.event);
|
|
3223
|
+
const body = {};
|
|
3224
|
+
if (values.url !== void 0) body.url = values.url;
|
|
3225
|
+
if (eventTypes !== void 0) body.eventTypes = eventTypes;
|
|
3226
|
+
if (values.description !== void 0) body.description = values.description;
|
|
3227
|
+
if (values.disabled) body.disabled = true;
|
|
3228
|
+
if (values.enabled) body.disabled = false;
|
|
3229
|
+
if (Object.keys(body).length === 0) {
|
|
3230
|
+
ctx.out.fail(
|
|
3231
|
+
"webhooks update: nothing to change \u2014 pass --url / --event / --description / --disabled / --enabled"
|
|
3232
|
+
);
|
|
3233
|
+
}
|
|
3234
|
+
if (!ctx.json) ctx.out.intro(`${badge5} update`);
|
|
3235
|
+
const res = await fetchOrFail2(
|
|
3236
|
+
ctx,
|
|
3237
|
+
"Updating webhook",
|
|
3238
|
+
() => ctx.http.patch(
|
|
3239
|
+
`/v1/admin/webhooks/${encodeURIComponent(id)}`,
|
|
3240
|
+
body
|
|
3241
|
+
)
|
|
3242
|
+
);
|
|
3243
|
+
if (ctx.json) {
|
|
3244
|
+
ctx.out.json(res);
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
renderEndpoint(ctx, res, "Endpoint updated");
|
|
3248
|
+
ctx.out.outro(`${color.green("Updated")} ${res.id} \u2192 ${res.status}`);
|
|
3249
|
+
}
|
|
3250
|
+
async function runDelete(ctx, argv) {
|
|
3251
|
+
const { values, positionals } = parseArgs14({
|
|
3252
|
+
args: argv,
|
|
3253
|
+
allowPositionals: true,
|
|
3254
|
+
options: { help: { type: "boolean", short: "h", default: false } }
|
|
3255
|
+
});
|
|
3256
|
+
if (values.help) {
|
|
3257
|
+
ctx.out.log(usage14);
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
const id = positionals[0];
|
|
3261
|
+
if (!id) {
|
|
3262
|
+
ctx.out.fail(
|
|
3263
|
+
"webhooks delete requires an endpoint id, e.g. hogsend webhooks delete we_123"
|
|
3264
|
+
);
|
|
3265
|
+
}
|
|
3266
|
+
if (!ctx.json) ctx.out.intro(`${badge5} delete`);
|
|
3267
|
+
const res = await fetchOrFail2(
|
|
3268
|
+
ctx,
|
|
3269
|
+
"Deleting webhook",
|
|
3270
|
+
() => ctx.http.del(
|
|
3271
|
+
`/v1/admin/webhooks/${encodeURIComponent(id)}`
|
|
3272
|
+
)
|
|
3273
|
+
);
|
|
3274
|
+
if (ctx.json) {
|
|
3275
|
+
ctx.out.json(res);
|
|
3276
|
+
return;
|
|
3277
|
+
}
|
|
3278
|
+
ctx.out.outro(`${color.green("Deleted")} ${id}`);
|
|
3279
|
+
}
|
|
3280
|
+
async function runRotate(ctx, argv) {
|
|
3281
|
+
const { values, positionals } = parseArgs14({
|
|
3282
|
+
args: argv,
|
|
3283
|
+
allowPositionals: true,
|
|
3284
|
+
options: { help: { type: "boolean", short: "h", default: false } }
|
|
3285
|
+
});
|
|
3286
|
+
if (values.help) {
|
|
3287
|
+
ctx.out.log(usage14);
|
|
3288
|
+
return;
|
|
3289
|
+
}
|
|
3290
|
+
const id = positionals[0];
|
|
3291
|
+
if (!id) {
|
|
3292
|
+
ctx.out.fail(
|
|
3293
|
+
"webhooks rotate-secret requires an endpoint id, e.g. hogsend webhooks rotate-secret we_123"
|
|
3294
|
+
);
|
|
3295
|
+
}
|
|
3296
|
+
if (!ctx.json) ctx.out.intro(`${badge5} rotate-secret`);
|
|
3297
|
+
const res = await fetchOrFail2(
|
|
3298
|
+
ctx,
|
|
3299
|
+
"Rotating signing secret",
|
|
3300
|
+
() => ctx.http.post(
|
|
3301
|
+
`/v1/admin/webhooks/${encodeURIComponent(id)}/rotate-secret`,
|
|
3302
|
+
{}
|
|
3303
|
+
)
|
|
3304
|
+
);
|
|
3305
|
+
if (ctx.json) {
|
|
3306
|
+
ctx.out.json(res);
|
|
3307
|
+
return;
|
|
3308
|
+
}
|
|
3309
|
+
ctx.out.kv({ id: res.id, secretPrefix: res.secretPrefix }, "Secret rotated");
|
|
3310
|
+
printSecretOnce(ctx, res.secret);
|
|
3311
|
+
ctx.out.outro(
|
|
3312
|
+
`${color.green("Rotated")} \u2014 the old secret is now invalid. Update every subscriber.`
|
|
3313
|
+
);
|
|
3314
|
+
}
|
|
3315
|
+
async function runTest(ctx, argv) {
|
|
3316
|
+
const { values, positionals } = parseArgs14({
|
|
3317
|
+
args: argv,
|
|
3318
|
+
allowPositionals: true,
|
|
3319
|
+
options: { help: { type: "boolean", short: "h", default: false } }
|
|
3320
|
+
});
|
|
3321
|
+
if (values.help) {
|
|
3322
|
+
ctx.out.log(usage14);
|
|
3323
|
+
return;
|
|
3324
|
+
}
|
|
3325
|
+
const id = positionals[0];
|
|
3326
|
+
if (!id) {
|
|
3327
|
+
ctx.out.fail(
|
|
3328
|
+
"webhooks test requires an endpoint id, e.g. hogsend webhooks test we_123"
|
|
3329
|
+
);
|
|
3330
|
+
}
|
|
3331
|
+
if (!ctx.json) ctx.out.intro(`${badge5} test`);
|
|
3332
|
+
const res = await fetchOrFail2(
|
|
3333
|
+
ctx,
|
|
3334
|
+
"Enqueuing test delivery",
|
|
3335
|
+
() => ctx.http.post(
|
|
3336
|
+
`/v1/admin/webhooks/${encodeURIComponent(id)}/test`,
|
|
3337
|
+
{}
|
|
3338
|
+
)
|
|
3339
|
+
);
|
|
3340
|
+
if (ctx.json) {
|
|
3341
|
+
ctx.out.json(res);
|
|
3342
|
+
return;
|
|
3343
|
+
}
|
|
3344
|
+
ctx.out.outro(
|
|
3345
|
+
`${color.green("Enqueued")} a ${color.cyan(res.eventType)} delivery to ${id}.`
|
|
3346
|
+
);
|
|
3347
|
+
}
|
|
3348
|
+
async function run14(ctx) {
|
|
3349
|
+
const sub = ctx.argv[0];
|
|
3350
|
+
switch (sub) {
|
|
3351
|
+
case "list":
|
|
3352
|
+
return runList4(ctx, ctx.argv.slice(1));
|
|
3353
|
+
case "get":
|
|
3354
|
+
return runGet3(ctx, ctx.argv.slice(1));
|
|
3355
|
+
case "create":
|
|
3356
|
+
return runCreate(ctx, ctx.argv.slice(1));
|
|
3357
|
+
case "update":
|
|
3358
|
+
return runUpdate(ctx, ctx.argv.slice(1));
|
|
3359
|
+
case "delete":
|
|
3360
|
+
return runDelete(ctx, ctx.argv.slice(1));
|
|
3361
|
+
case "rotate-secret":
|
|
3362
|
+
return runRotate(ctx, ctx.argv.slice(1));
|
|
3363
|
+
case "test":
|
|
3364
|
+
return runTest(ctx, ctx.argv.slice(1));
|
|
3365
|
+
case void 0:
|
|
3366
|
+
ctx.out.fail(
|
|
3367
|
+
"webhooks requires a subcommand: list | get | create | update | delete | rotate-secret | test (see hogsend webhooks --help)"
|
|
3368
|
+
);
|
|
3369
|
+
break;
|
|
3370
|
+
default:
|
|
3371
|
+
ctx.out.fail(
|
|
3372
|
+
`unknown webhooks subcommand "${sub}" \u2014 expected one of list | get | create | update | delete | rotate-secret | test`
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
var webhooksCommand = {
|
|
3377
|
+
name: "webhooks",
|
|
3378
|
+
summary: "Manage outbound webhook endpoints (create, rotate, test)",
|
|
3379
|
+
usage: usage14,
|
|
3380
|
+
run: run14
|
|
3381
|
+
};
|
|
3382
|
+
|
|
2947
3383
|
// src/commands/index.ts
|
|
2948
3384
|
var commands = [
|
|
2949
3385
|
doctorCommand,
|
|
@@ -2953,6 +3389,7 @@ var commands = [
|
|
|
2953
3389
|
eventsCommand,
|
|
2954
3390
|
emailsCommand,
|
|
2955
3391
|
campaignsCommand,
|
|
3392
|
+
webhooksCommand,
|
|
2956
3393
|
studioCommand,
|
|
2957
3394
|
setupCommand,
|
|
2958
3395
|
skillsCommand,
|
|
@@ -2964,10 +3401,10 @@ var commands = [
|
|
|
2964
3401
|
// src/lib/config.ts
|
|
2965
3402
|
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
2966
3403
|
import { join as join8 } from "path";
|
|
2967
|
-
import { parseArgs as
|
|
3404
|
+
import { parseArgs as parseArgs15 } from "util";
|
|
2968
3405
|
var DEFAULT_BASE_URL = "http://localhost:3002";
|
|
2969
3406
|
function parseGlobalFlags(argv) {
|
|
2970
|
-
const { values, tokens } =
|
|
3407
|
+
const { values, tokens } = parseArgs15({
|
|
2971
3408
|
args: argv,
|
|
2972
3409
|
allowPositionals: true,
|
|
2973
3410
|
strict: false,
|