@eve-horizon/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleEvent = handleEvent;
4
+ const args_1 = require("../lib/args");
5
+ const client_1 = require("../lib/client");
6
+ const output_1 = require("../lib/output");
7
+ // ============================================================================
8
+ // Main Handler
9
+ // ============================================================================
10
+ async function handleEvent(subcommand, positionals, flags, context) {
11
+ const json = Boolean(flags.json);
12
+ switch (subcommand) {
13
+ case 'list':
14
+ return handleList(positionals, flags, context, json);
15
+ case 'show':
16
+ return handleShow(positionals, flags, context, json);
17
+ case 'emit':
18
+ return handleEmit(flags, context, json);
19
+ default:
20
+ throw new Error('Usage: eve event <list|show|emit>\n' +
21
+ ' list [project] - list events for a project\n' +
22
+ ' show <event_id> - show details of an event\n' +
23
+ ' emit --type=<type> --source=<source> - emit a new event (for testing)');
24
+ }
25
+ }
26
+ // ============================================================================
27
+ // Subcommand Handlers
28
+ // ============================================================================
29
+ /**
30
+ * eve event list [project] [--type] [--source] [--status] [--limit] [--offset]
31
+ * List events for a project
32
+ */
33
+ async function handleList(positionals, flags, context, json) {
34
+ const projectId = positionals[0] ?? (0, args_1.getStringFlag)(flags, ['project']) ?? context.projectId;
35
+ if (!projectId) {
36
+ throw new Error('Usage: eve event list [project] [--project=<id>] [--type=<type>] [--source=<source>] [--status=<status>]');
37
+ }
38
+ const query = buildQuery({
39
+ type: (0, args_1.getStringFlag)(flags, ['type']),
40
+ source: (0, args_1.getStringFlag)(flags, ['source']),
41
+ status: (0, args_1.getStringFlag)(flags, ['status']),
42
+ limit: (0, args_1.getStringFlag)(flags, ['limit']),
43
+ offset: (0, args_1.getStringFlag)(flags, ['offset']),
44
+ });
45
+ const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/events${query}`);
46
+ if (json) {
47
+ (0, output_1.outputJson)(response, json);
48
+ }
49
+ else {
50
+ if (response.data.length === 0) {
51
+ console.log('No events found.');
52
+ return;
53
+ }
54
+ formatEventsTable(response.data);
55
+ }
56
+ }
57
+ /**
58
+ * eve event show <event_id>
59
+ * Show details of an event
60
+ */
61
+ async function handleShow(positionals, flags, context, json) {
62
+ const eventId = positionals[0] ?? (0, args_1.getStringFlag)(flags, ['id', 'event']);
63
+ const projectId = (0, args_1.getStringFlag)(flags, ['project']) ?? context.projectId;
64
+ if (!eventId) {
65
+ throw new Error('Usage: eve event show <event_id> [--id=<id>]');
66
+ }
67
+ if (!projectId) {
68
+ throw new Error('Project ID is required. Use --project=<id> or set a default project in your profile.');
69
+ }
70
+ const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/events/${eventId}`);
71
+ if (json) {
72
+ (0, output_1.outputJson)(response, json);
73
+ }
74
+ else {
75
+ formatEventDetails(response);
76
+ }
77
+ }
78
+ /**
79
+ * eve event emit --type=<type> --source=<source> [--env] [--payload]
80
+ * Emit a new event (for testing)
81
+ */
82
+ async function handleEmit(flags, context, json) {
83
+ const projectId = (0, args_1.getStringFlag)(flags, ['project']) ?? context.projectId;
84
+ const type = (0, args_1.getStringFlag)(flags, ['type']);
85
+ const source = (0, args_1.getStringFlag)(flags, ['source']);
86
+ if (!projectId) {
87
+ throw new Error('Usage: eve event emit --project=<id> --type=<type> --source=<source> [options]');
88
+ }
89
+ if (!type) {
90
+ throw new Error('--type is required (e.g., "github.push", "cron.tick", "app.event")');
91
+ }
92
+ if (!source) {
93
+ throw new Error('--source is required (e.g., "github", "cron", "manual", "app", "system")');
94
+ }
95
+ const body = {
96
+ type,
97
+ source,
98
+ };
99
+ // Optional fields
100
+ const envName = (0, args_1.getStringFlag)(flags, ['env', 'env-name']);
101
+ if (envName) {
102
+ body.env_name = envName;
103
+ }
104
+ const refSha = (0, args_1.getStringFlag)(flags, ['ref-sha', 'sha']);
105
+ if (refSha) {
106
+ body.ref_sha = refSha;
107
+ }
108
+ const refBranch = (0, args_1.getStringFlag)(flags, ['ref-branch', 'branch']);
109
+ if (refBranch) {
110
+ body.ref_branch = refBranch;
111
+ }
112
+ const actorType = (0, args_1.getStringFlag)(flags, ['actor-type']);
113
+ if (actorType) {
114
+ body.actor_type = actorType;
115
+ }
116
+ const actorId = (0, args_1.getStringFlag)(flags, ['actor-id', 'actor']);
117
+ if (actorId) {
118
+ body.actor_id = actorId;
119
+ }
120
+ const dedupeKey = (0, args_1.getStringFlag)(flags, ['dedupe-key']);
121
+ if (dedupeKey) {
122
+ body.dedupe_key = dedupeKey;
123
+ }
124
+ // Payload as JSON string
125
+ const payloadStr = (0, args_1.getStringFlag)(flags, ['payload']);
126
+ if (payloadStr) {
127
+ try {
128
+ body.payload_json = JSON.parse(payloadStr);
129
+ }
130
+ catch (error) {
131
+ throw new Error(`Invalid JSON in --payload: ${error.message}`);
132
+ }
133
+ }
134
+ const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/events`, {
135
+ method: 'POST',
136
+ body,
137
+ });
138
+ if (json) {
139
+ (0, output_1.outputJson)(response, json);
140
+ }
141
+ else {
142
+ console.log(`Event created: ${response.id}`);
143
+ console.log(` Type: ${response.type}`);
144
+ console.log(` Source: ${response.source}`);
145
+ console.log(` Status: ${response.status}`);
146
+ if (response.env_name) {
147
+ console.log(` Env: ${response.env_name}`);
148
+ }
149
+ if (response.ref_sha) {
150
+ console.log(` SHA: ${response.ref_sha}`);
151
+ }
152
+ if (response.ref_branch) {
153
+ console.log(` Branch: ${response.ref_branch}`);
154
+ }
155
+ }
156
+ }
157
+ // ============================================================================
158
+ // Helper Functions
159
+ // ============================================================================
160
+ /**
161
+ * Build query string from parameters
162
+ */
163
+ function buildQuery(params) {
164
+ const search = new URLSearchParams();
165
+ Object.entries(params).forEach(([key, value]) => {
166
+ if (value === undefined || value === '')
167
+ return;
168
+ search.set(key, String(value));
169
+ });
170
+ const query = search.toString();
171
+ return query ? `?${query}` : '';
172
+ }
173
+ /**
174
+ * Format events as a human-readable table
175
+ */
176
+ function formatEventsTable(events) {
177
+ if (events.length === 0) {
178
+ console.log('No events found.');
179
+ return;
180
+ }
181
+ // Calculate column widths
182
+ const idWidth = Math.max(8, ...events.map((e) => e.id.length));
183
+ const typeWidth = Math.max(4, ...events.map((e) => e.type.length));
184
+ const sourceWidth = Math.max(6, ...events.map((e) => e.source.length));
185
+ const statusWidth = Math.max(6, ...events.map((e) => e.status.length));
186
+ // Header
187
+ const header = [
188
+ padRight('ID', idWidth),
189
+ padRight('Type', typeWidth),
190
+ padRight('Source', sourceWidth),
191
+ padRight('Status', statusWidth),
192
+ padRight('Env', 12),
193
+ padRight('Branch', 20),
194
+ 'Created',
195
+ ].join(' ');
196
+ console.log(header);
197
+ console.log('-'.repeat(header.length));
198
+ // Rows
199
+ for (const event of events) {
200
+ const row = [
201
+ padRight(event.id, idWidth),
202
+ padRight(event.type, typeWidth),
203
+ padRight(event.source, sourceWidth),
204
+ padRight(event.status, statusWidth),
205
+ padRight(event.env_name || '-', 12),
206
+ padRight(event.ref_branch || '-', 20),
207
+ formatDate(event.created_at),
208
+ ].join(' ');
209
+ console.log(row);
210
+ }
211
+ console.log('');
212
+ console.log(`Total: ${events.length} event(s)`);
213
+ }
214
+ /**
215
+ * Format a single event's details
216
+ */
217
+ function formatEventDetails(event) {
218
+ console.log(`Event: ${event.id}`);
219
+ console.log('');
220
+ console.log(` Project: ${event.project_id}`);
221
+ console.log(` Type: ${event.type}`);
222
+ console.log(` Source: ${event.source}`);
223
+ console.log(` Status: ${event.status}`);
224
+ if (event.env_name) {
225
+ console.log(` Environment: ${event.env_name}`);
226
+ }
227
+ if (event.ref_sha) {
228
+ console.log(` Ref SHA: ${event.ref_sha}`);
229
+ }
230
+ if (event.ref_branch) {
231
+ console.log(` Ref Branch: ${event.ref_branch}`);
232
+ }
233
+ if (event.actor_type) {
234
+ console.log(` Actor Type: ${event.actor_type}`);
235
+ }
236
+ if (event.actor_id) {
237
+ console.log(` Actor ID: ${event.actor_id}`);
238
+ }
239
+ if (event.dedupe_key) {
240
+ console.log(` Dedupe Key: ${event.dedupe_key}`);
241
+ }
242
+ if (event.payload_json && Object.keys(event.payload_json).length > 0) {
243
+ console.log('');
244
+ console.log(' Payload:');
245
+ console.log(` ${JSON.stringify(event.payload_json, null, 2).split('\n').join('\n ')}`);
246
+ }
247
+ console.log('');
248
+ console.log(` Created: ${formatDate(event.created_at)}`);
249
+ console.log(` Updated: ${formatDate(event.updated_at)}`);
250
+ if (event.processed_at) {
251
+ console.log(` Processed: ${formatDate(event.processed_at)}`);
252
+ }
253
+ }
254
+ /**
255
+ * Format a date string for display
256
+ */
257
+ function formatDate(dateStr) {
258
+ try {
259
+ const date = new Date(dateStr);
260
+ return date.toLocaleString();
261
+ }
262
+ catch {
263
+ return dateStr;
264
+ }
265
+ }
266
+ /**
267
+ * Pad a string to the right with spaces
268
+ */
269
+ function padRight(str, width) {
270
+ if (str.length >= width)
271
+ return str;
272
+ return str + ' '.repeat(width - str.length);
273
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleHarness = handleHarness;
4
+ const client_1 = require("../lib/client");
5
+ const output_1 = require("../lib/output");
6
+ async function handleHarness(subcommand, positionals, flags, context) {
7
+ const json = Boolean(flags.json);
8
+ switch (subcommand) {
9
+ case 'list': {
10
+ const response = await (0, client_1.requestJson)(context, '/harnesses');
11
+ if (json) {
12
+ (0, output_1.outputJson)(response, json);
13
+ return;
14
+ }
15
+ renderHarnessList(response.data);
16
+ return;
17
+ }
18
+ case 'get': {
19
+ const name = positionals[0];
20
+ if (!name)
21
+ throw new Error('Usage: eve harness get <name>');
22
+ const response = await (0, client_1.requestJson)(context, `/harnesses/${name}`);
23
+ if (json) {
24
+ (0, output_1.outputJson)(response, json);
25
+ return;
26
+ }
27
+ renderHarnessDetail(response);
28
+ return;
29
+ }
30
+ default:
31
+ throw new Error('Usage: eve harness <list|get>');
32
+ }
33
+ }
34
+ function renderHarnessList(harnesses) {
35
+ const rows = harnesses.map((harness) => {
36
+ const variants = harness.variants
37
+ .map((variant) => variant.name)
38
+ .join(', ') || 'default';
39
+ const auth = harness.auth.available ? 'ready' : 'missing';
40
+ const name = formatHarnessLabel(harness);
41
+ const description = truncate(harness.description, 64);
42
+ return { name, variants, auth, description };
43
+ });
44
+ const headers = ['Harness', 'Variants', 'Auth', 'Description'];
45
+ const widths = [
46
+ Math.max(headers[0].length, ...rows.map((row) => row.name.length)),
47
+ Math.max(headers[1].length, ...rows.map((row) => row.variants.length)),
48
+ Math.max(headers[2].length, ...rows.map((row) => row.auth.length)),
49
+ Math.max(headers[3].length, ...rows.map((row) => row.description.length)),
50
+ ];
51
+ const line = `+${widths.map((w) => '-'.repeat(w + 2)).join('+')}+`;
52
+ const mid = `+${widths.map((w) => '-'.repeat(w + 2)).join('+')}+`;
53
+ const end = `+${widths.map((w) => '-'.repeat(w + 2)).join('+')}+`;
54
+ console.log(line);
55
+ console.log(formatRow(headers, widths));
56
+ console.log(mid);
57
+ for (const row of rows) {
58
+ console.log(formatRow([row.name, row.variants, row.auth, row.description], widths));
59
+ }
60
+ console.log(end);
61
+ }
62
+ function renderHarnessDetail(harness) {
63
+ const variants = harness.variants.length
64
+ ? harness.variants
65
+ : [{ name: 'default', description: 'Default harness configuration' }];
66
+ console.log(`Harness: ${harness.name}`);
67
+ if (harness.aliases?.length) {
68
+ console.log(`Aliases: ${harness.aliases.join(', ')}`);
69
+ }
70
+ console.log(`Description: ${harness.description}`);
71
+ console.log('Variants:');
72
+ for (const variant of variants) {
73
+ console.log(` - ${variant.name}: ${variant.description}`);
74
+ }
75
+ console.log('Auth:');
76
+ console.log(` - Status: ${harness.auth.available ? 'ready' : 'missing'}`);
77
+ console.log(` - Details: ${harness.auth.reason}`);
78
+ console.log(' - To enable:');
79
+ for (const instruction of harness.auth.instructions) {
80
+ console.log(` - ${instruction}`);
81
+ }
82
+ }
83
+ function formatHarnessLabel(harness) {
84
+ if (!harness.aliases?.length)
85
+ return harness.name;
86
+ return `${harness.name} (aliases: ${harness.aliases.join(', ')})`;
87
+ }
88
+ function formatRow(columns, widths) {
89
+ const cells = columns.map((value, idx) => ` ${value.padEnd(widths[idx])} `);
90
+ return `|${cells.join('|')}|`;
91
+ }
92
+ function truncate(value, max) {
93
+ if (value.length <= max)
94
+ return value;
95
+ return `${value.slice(0, Math.max(0, max - 3))}...`;
96
+ }