@hasna/machines 0.0.29 → 0.0.30
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/cli/index.js +20 -14
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -3164,9 +3164,15 @@ function print(value, json, text) {
|
|
|
3164
3164
|
else
|
|
3165
3165
|
console.log(text);
|
|
3166
3166
|
}
|
|
3167
|
+
function hasJsonOption(options) {
|
|
3168
|
+
return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
|
|
3169
|
+
}
|
|
3170
|
+
function wantsJson(actionOptions, command) {
|
|
3171
|
+
return hasJsonOption(actionOptions) || hasJsonOption(command);
|
|
3172
|
+
}
|
|
3167
3173
|
function registerWebhookCommands(program2, options) {
|
|
3168
3174
|
const webhooks = program2.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
|
|
3169
|
-
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
|
|
3175
|
+
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
|
|
3170
3176
|
const timestamp = new Date().toISOString();
|
|
3171
3177
|
const channel = {
|
|
3172
3178
|
id: actionOptions.id,
|
|
@@ -3187,11 +3193,11 @@ function registerWebhookCommands(program2, options) {
|
|
|
3187
3193
|
throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
|
|
3188
3194
|
}
|
|
3189
3195
|
const saved = await createClient(options).addChannel(channel);
|
|
3190
|
-
print(sanitizeChannelForOutput(saved),
|
|
3196
|
+
print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
|
|
3191
3197
|
});
|
|
3192
|
-
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
3198
|
+
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
3193
3199
|
const channels = await createClient(options).listChannels();
|
|
3194
|
-
if (actionOptions
|
|
3200
|
+
if (wantsJson(actionOptions, command)) {
|
|
3195
3201
|
console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
|
|
3196
3202
|
return;
|
|
3197
3203
|
}
|
|
@@ -3203,11 +3209,11 @@ function registerWebhookCommands(program2, options) {
|
|
|
3203
3209
|
console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
|
|
3204
3210
|
}
|
|
3205
3211
|
});
|
|
3206
|
-
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
3212
|
+
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
3207
3213
|
const removed = await createClient(options).removeChannel(id);
|
|
3208
|
-
print({ removed },
|
|
3214
|
+
print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
|
|
3209
3215
|
});
|
|
3210
|
-
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
3216
|
+
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
3211
3217
|
const result = await createClient(options).testChannel(id, {
|
|
3212
3218
|
source: options.source,
|
|
3213
3219
|
type: actionOptions.type,
|
|
@@ -3215,13 +3221,13 @@ function registerWebhookCommands(program2, options) {
|
|
|
3215
3221
|
message: actionOptions.message,
|
|
3216
3222
|
data: parseJsonObject(actionOptions.data, { test: true })
|
|
3217
3223
|
});
|
|
3218
|
-
print(result,
|
|
3224
|
+
print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
|
|
3219
3225
|
});
|
|
3220
3226
|
return webhooks;
|
|
3221
3227
|
}
|
|
3222
3228
|
function registerEventCommands(program2, options) {
|
|
3223
3229
|
const events = program2.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
|
|
3224
|
-
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
|
|
3230
|
+
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions, command) => {
|
|
3225
3231
|
const result = await createClient(options).emit({
|
|
3226
3232
|
source: actionOptions.source ?? options.source,
|
|
3227
3233
|
type,
|
|
@@ -3232,9 +3238,9 @@ function registerEventCommands(program2, options) {
|
|
|
3232
3238
|
data: parseJsonObject(actionOptions.data, {}),
|
|
3233
3239
|
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
3234
3240
|
}, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
|
|
3235
|
-
print(result,
|
|
3241
|
+
print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
|
|
3236
3242
|
});
|
|
3237
|
-
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
3243
|
+
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
3238
3244
|
let rows = await createClient(options).listEvents();
|
|
3239
3245
|
if (actionOptions.source)
|
|
3240
3246
|
rows = rows.filter((event) => event.source === actionOptions.source);
|
|
@@ -3242,7 +3248,7 @@ function registerEventCommands(program2, options) {
|
|
|
3242
3248
|
rows = rows.filter((event) => event.type === actionOptions.type);
|
|
3243
3249
|
if (actionOptions.limit)
|
|
3244
3250
|
rows = rows.slice(-actionOptions.limit);
|
|
3245
|
-
if (actionOptions
|
|
3251
|
+
if (wantsJson(actionOptions, command)) {
|
|
3246
3252
|
console.log(JSON.stringify(rows, null, 2));
|
|
3247
3253
|
return;
|
|
3248
3254
|
}
|
|
@@ -3253,14 +3259,14 @@ function registerEventCommands(program2, options) {
|
|
|
3253
3259
|
for (const event of rows)
|
|
3254
3260
|
console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
|
|
3255
3261
|
});
|
|
3256
|
-
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
3262
|
+
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
3257
3263
|
const result = await createClient(options).replay({
|
|
3258
3264
|
eventId: actionOptions.id,
|
|
3259
3265
|
source: actionOptions.source,
|
|
3260
3266
|
type: actionOptions.type,
|
|
3261
3267
|
dryRun: actionOptions.dryRun
|
|
3262
3268
|
});
|
|
3263
|
-
print(result,
|
|
3269
|
+
print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
|
|
3264
3270
|
});
|
|
3265
3271
|
return events;
|
|
3266
3272
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/machines",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"description": "Machine fleet management CLI + MCP for developers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"bun": ">=1.0.0"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@hasna/events": "^0.1.
|
|
70
|
+
"@hasna/events": "^0.1.7",
|
|
71
71
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
72
72
|
"chalk": "^5.6.2",
|
|
73
73
|
"commander": "^13.1.0",
|