@simonfestl/husky-cli 0.8.2 → 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.
Files changed (44) hide show
  1. package/README.md +3 -116
  2. package/dist/commands/biz/customers.d.ts +8 -0
  3. package/dist/commands/biz/customers.js +181 -0
  4. package/dist/commands/biz/orders.d.ts +8 -0
  5. package/dist/commands/biz/orders.js +226 -0
  6. package/dist/commands/biz/products.d.ts +8 -0
  7. package/dist/commands/biz/products.js +255 -0
  8. package/dist/commands/biz/qdrant.d.ts +8 -0
  9. package/dist/commands/biz/qdrant.js +170 -0
  10. package/dist/commands/biz/seatable.d.ts +8 -0
  11. package/dist/commands/biz/seatable.js +449 -0
  12. package/dist/commands/biz/tickets.d.ts +8 -0
  13. package/dist/commands/biz/tickets.js +600 -0
  14. package/dist/commands/biz.d.ts +9 -0
  15. package/dist/commands/biz.js +22 -0
  16. package/dist/commands/config.d.ts +13 -0
  17. package/dist/commands/config.js +43 -16
  18. package/dist/commands/explain.js +12 -595
  19. package/dist/commands/idea.js +2 -50
  20. package/dist/commands/project.js +2 -47
  21. package/dist/commands/roadmap.js +0 -107
  22. package/dist/commands/task.js +11 -17
  23. package/dist/commands/vm.js +0 -225
  24. package/dist/commands/workflow.js +4 -60
  25. package/dist/index.js +5 -1
  26. package/dist/lib/biz/billbee-types.d.ts +259 -0
  27. package/dist/lib/biz/billbee-types.js +41 -0
  28. package/dist/lib/biz/billbee.d.ts +37 -0
  29. package/dist/lib/biz/billbee.js +165 -0
  30. package/dist/lib/biz/embeddings.d.ts +45 -0
  31. package/dist/lib/biz/embeddings.js +115 -0
  32. package/dist/lib/biz/index.d.ts +13 -0
  33. package/dist/lib/biz/index.js +11 -0
  34. package/dist/lib/biz/qdrant.d.ts +52 -0
  35. package/dist/lib/biz/qdrant.js +158 -0
  36. package/dist/lib/biz/seatable-types.d.ts +115 -0
  37. package/dist/lib/biz/seatable-types.js +27 -0
  38. package/dist/lib/biz/seatable.d.ts +49 -0
  39. package/dist/lib/biz/seatable.js +210 -0
  40. package/dist/lib/biz/zendesk-types.d.ts +136 -0
  41. package/dist/lib/biz/zendesk-types.js +28 -0
  42. package/dist/lib/biz/zendesk.d.ts +45 -0
  43. package/dist/lib/biz/zendesk.js +206 -0
  44. package/package.json +2 -2
package/README.md CHANGED
@@ -1,8 +1,5 @@
1
1
  # Husky CLI
2
2
 
3
- [![CLI Tests](https://github.com/simon-sfxecom/huskyv0/actions/workflows/cli-tests.yml/badge.svg)](https://github.com/simon-sfxecom/huskyv0/actions/workflows/cli-tests.yml)
4
- [![codecov](https://codecov.io/gh/simon-sfxecom/huskyv0/branch/main/graph/badge.svg?flag=cli)](https://codecov.io/gh/simon-sfxecom/huskyv0)
5
-
6
3
  CLI for Huskyv0 Task Orchestration with Claude Agent SDK integration.
7
4
 
8
5
  **Part of the [huskyv0 monorepo](https://github.com/simon-sfxecom/huskyv0)**
@@ -42,8 +39,6 @@ husky
42
39
  husky task list # List all tasks
43
40
  husky task list --status in_progress # Filter by status
44
41
  husky task list --json # JSON output
45
- husky task list -i # Interactive pagination
46
- husky task list --per-page 10 --page 2 # Paginated output
47
42
  husky task create "Fix login bug" --priority high
48
43
  husky task get <task-id>
49
44
  husky task start <task-id>
@@ -55,9 +50,7 @@ husky task delete <task-id>
55
50
  ### Project Management
56
51
 
57
52
  ```bash
58
- husky project list # List all projects
59
- husky project list -i # Interactive pagination
60
- husky project list --per-page 5 --page 1 # Paginated output
53
+ husky project list
61
54
  husky project create "New Project" --description "..."
62
55
  husky project get <project-id>
63
56
  husky project update <project-id> --status active
@@ -70,9 +63,7 @@ husky project delete-knowledge <project-id> <knowledge-id>
70
63
  ### Workflow Management
71
64
 
72
65
  ```bash
73
- husky workflow list # List all workflows
74
- husky workflow list -i # Interactive pagination
75
- husky workflow list --per-page 5 # Paginated output
66
+ husky workflow list
76
67
  husky workflow create "Onboarding" --department <id>
77
68
  husky workflow get <workflow-id>
78
69
  husky workflow update <workflow-id> --name "Updated"
@@ -87,9 +78,7 @@ husky workflow generate-mermaid <workflow-id> # Mermaid diagram
87
78
  ### Idea Management
88
79
 
89
80
  ```bash
90
- husky idea list # List all ideas
91
- husky idea list -i # Interactive pagination
92
- husky idea list --per-page 10 # Paginated output
81
+ husky idea list
93
82
  husky idea create "New feature idea" --category feature
94
83
  husky idea get <idea-id>
95
84
  husky idea update <idea-id> --status approved
@@ -171,8 +160,6 @@ husky roadmap create "Q1 2025" --description "..."
171
160
  husky roadmap update <roadmap-id> --name "Updated"
172
161
  husky roadmap delete <roadmap-id>
173
162
  husky roadmap add-phase <roadmap-id> --name "Phase 1"
174
- husky roadmap update-phase <roadmap-id> <phase-id> --name "Updated"
175
- husky roadmap delete-phase <roadmap-id> <phase-id> --force
176
163
  husky roadmap add-feature <roadmap-id> --phase <id> --title "Feature"
177
164
  husky roadmap list-features <roadmap-id>
178
165
  husky roadmap update-feature <roadmap-id> <feature-id> --status done
@@ -200,20 +187,6 @@ husky vm-config update <config-id> --machine-type e2-standard-2
200
187
  husky vm-config delete <config-id>
201
188
  ```
202
189
 
203
- ### Git Worktree Management
204
-
205
- ```bash
206
- husky worktree list # List all worktrees
207
- husky worktree create <session-name> # Create worktree
208
- husky worktree info <session-name> # Show details
209
- husky worktree status [session-name] # Show status
210
- husky worktree cd <session-name> # Print path
211
- husky worktree merge <session-name> # Merge to base
212
- husky worktree remove <session-name> # Remove worktree
213
- husky worktree branches # List husky/* branches
214
- husky worktree cleanup # Clean stale worktrees
215
- ```
216
-
217
190
  ### Settings
218
191
 
219
192
  ```bash
@@ -248,35 +221,6 @@ husky completion zsh >> ~/.zshrc
248
221
  husky completion fish > ~/.config/fish/completions/husky.fish
249
222
  ```
250
223
 
251
- ## Pagination
252
-
253
- List commands support pagination with two modes:
254
-
255
- ### Interactive Pagination (`-i`)
256
-
257
- Navigate through results using arrow keys:
258
-
259
- ```bash
260
- husky task list -i # Interactive mode with arrow key navigation
261
- husky project list -i # Works for projects, ideas, workflows
262
- ```
263
-
264
- Features:
265
- - Use `↑`/`↓` to navigate items
266
- - `←` Previous page / `→` Next page
267
- - Press `Enter` to select and view details
268
- - Press `Esc` or select "Exit" to return
269
-
270
- ### Static Pagination (`--page`, `--per-page`)
271
-
272
- For scripting or quick page views:
273
-
274
- ```bash
275
- husky task list --per-page 10 # Show first 10 items
276
- husky task list --per-page 10 --page 2 # Show items 11-20
277
- husky idea list -n 5 -p 3 # Short form: 5 items, page 3
278
- ```
279
-
280
224
  ## Environment Variables
281
225
 
282
226
  | Variable | Description |
@@ -339,22 +283,6 @@ husky --version
339
283
 
340
284
  ## Changelog
341
285
 
342
- ### v0.6.2 (2026-01-06)
343
- - Added: Interactive pagination for list commands (`-i` flag)
344
- - Added: Static pagination (`--page`, `--per-page` flags)
345
- - Improved: Tasks, projects, ideas, workflows now support pagination
346
-
347
- ### v0.6.1 (2026-01-06)
348
- - Added: Roadmap phase management (`update-phase`, `delete-phase`)
349
- - Fixed: Various bug fixes
350
-
351
- ### v0.6.0 (2026-01-06)
352
- - Added: Git Worktree support for multi-agent isolation
353
- - Added: `husky worktree` commands (create, list, merge, remove, etc.)
354
- - Added: MergeLock mechanism for safe concurrent operations
355
- - Refactored: Interactive mode into modular components
356
- - Improved: Based on Auto-Claude's worktree architecture
357
-
358
286
  ### v0.5.0 (2026-01-06)
359
287
  - Full Dashboard feature parity (69 new commands)
360
288
  - Added: project, workflow, idea, department, vm, jules, process, strategy, settings, vm-config commands
@@ -381,47 +309,6 @@ husky --version
381
309
  - Configuration management
382
310
  - API key authentication
383
311
 
384
- ## Development
385
-
386
- ### Testing
387
-
388
- The CLI has comprehensive test coverage using Vitest:
389
-
390
- ```bash
391
- # Run all tests
392
- npm test
393
-
394
- # Run tests in watch mode
395
- npm run test:watch
396
-
397
- # Run with coverage
398
- npm run test:coverage
399
-
400
- # Run specific test file
401
- npm test tests/unit/commands/config.test.ts
402
- ```
403
-
404
- **Test Structure:**
405
- - `tests/setup.ts` - Global test configuration (MSW, memfs, mocks)
406
- - `tests/unit/` - Unit tests for individual modules
407
- - `tests/integration/` - Integration tests for workflows
408
- - `tests/helpers/` - Reusable mocking utilities
409
-
410
- **Current Coverage:**
411
- - Config Command: ~29% lines, 60% functions
412
- - Worktree Library: ~55% lines, 70% branches, 65% functions
413
- - Total: 29 tests across 4 test files
414
-
415
- ### Building
416
-
417
- ```bash
418
- # Build TypeScript
419
- npm run build
420
-
421
- # Watch mode for development
422
- npm run dev
423
- ```
424
-
425
312
  ## License
426
313
 
427
314
  MIT
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Husky Biz Customers Command
3
+ *
4
+ * Access customer profiles via Billbee (from order data)
5
+ */
6
+ import { Command } from "commander";
7
+ export declare const customersCommand: Command;
8
+ export default customersCommand;
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Husky Biz Customers Command
3
+ *
4
+ * Access customer profiles via Billbee (from order data)
5
+ */
6
+ import { Command } from "commander";
7
+ import { BillbeeClient } from "../../lib/biz/index.js";
8
+ export const customersCommand = new Command("customers")
9
+ .description("Access customer profiles (Billbee)");
10
+ // husky biz customers search <email>
11
+ customersCommand
12
+ .command("search <email>")
13
+ .description("Search customers by email")
14
+ .option("--json", "Output as JSON")
15
+ .action(async (email, options) => {
16
+ try {
17
+ const client = BillbeeClient.fromConfig();
18
+ const result = await client.findCustomerByEmail(email);
19
+ if (!result) {
20
+ console.log(`\n No customer found with email: ${email}\n`);
21
+ process.exit(0);
22
+ }
23
+ if (options.json) {
24
+ console.log(JSON.stringify(result, null, 2));
25
+ return;
26
+ }
27
+ console.log(`\n 👤 Customer: ${email}`);
28
+ console.log(" " + "─".repeat(40));
29
+ const addr = result.address;
30
+ if (addr) {
31
+ console.log(` Name: ${addr.FirstName || ""} ${addr.LastName || ""}`);
32
+ if (addr.Company)
33
+ console.log(` Company: ${addr.Company}`);
34
+ console.log(` Address: ${addr.Street || ""} ${addr.HouseNumber || ""}`);
35
+ console.log(` ${addr.Zip || ""} ${addr.City || ""}`);
36
+ if (addr.Phone)
37
+ console.log(` Phone: ${addr.Phone}`);
38
+ }
39
+ console.log(`\n Orders: ${result.orders.length}`);
40
+ console.log("");
41
+ }
42
+ catch (error) {
43
+ console.error("Error:", error.message);
44
+ process.exit(1);
45
+ }
46
+ });
47
+ // husky biz customers history <email>
48
+ customersCommand
49
+ .command("history <email>")
50
+ .description("Get order history for customer by email")
51
+ .option("-l, --limit <num>", "Max orders to show", "10")
52
+ .option("--json", "Output as JSON")
53
+ .action(async (email, options) => {
54
+ try {
55
+ const client = BillbeeClient.fromConfig();
56
+ const result = await client.findCustomerByEmail(email);
57
+ if (!result) {
58
+ console.log(`\n No customer found with email: ${email}\n`);
59
+ process.exit(0);
60
+ }
61
+ const orders = result.orders.slice(0, parseInt(options.limit, 10));
62
+ if (options.json) {
63
+ console.log(JSON.stringify(orders, null, 2));
64
+ return;
65
+ }
66
+ const addr = result.address;
67
+ const name = addr ? `${addr.FirstName || ""} ${addr.LastName || ""}`.trim() : email;
68
+ console.log(`\n 📋 Order History for ${name} (${email})`);
69
+ console.log(" " + "─".repeat(60));
70
+ console.log(`\n ${result.orders.length} total orders\n`);
71
+ if (orders.length === 0) {
72
+ console.log(" No orders found.");
73
+ return;
74
+ }
75
+ for (const order of orders) {
76
+ const date = order.CreatedAt ? new Date(order.CreatedAt).toLocaleDateString("de-DE") : "?";
77
+ const total = order.TotalCost?.toFixed(2) || "0.00";
78
+ console.log(` #${(order.OrderNumber || "?").padEnd(12)} │ ${date} │ €${total}`);
79
+ }
80
+ console.log("");
81
+ }
82
+ catch (error) {
83
+ console.error("Error:", error.message);
84
+ process.exit(1);
85
+ }
86
+ });
87
+ // ============================================================================
88
+ // PREBUILD COMMANDS
89
+ // ============================================================================
90
+ import { ZendeskClient } from "../../lib/biz/index.js";
91
+ // husky biz customers 360 <email>
92
+ customersCommand
93
+ .command("360 <email>")
94
+ .alias("full")
95
+ .description("[PREBUILD] Full customer view (Billbee orders + Zendesk tickets)")
96
+ .option("--json", "Output as JSON")
97
+ .action(async (email, options) => {
98
+ try {
99
+ const billbee = BillbeeClient.fromConfig();
100
+ const zendesk = ZendeskClient.fromConfig();
101
+ // Parallel fetch from both systems
102
+ console.log(` Fetching customer data for ${email}...`);
103
+ const [customerResult, tickets] = await Promise.all([
104
+ billbee.findCustomerByEmail(email).catch(() => null),
105
+ zendesk.searchTickets(`requester:${email}`).catch(() => []),
106
+ ]);
107
+ const result = {
108
+ email,
109
+ billbee: customerResult ? {
110
+ name: customerResult.address
111
+ ? `${customerResult.address.FirstName || ''} ${customerResult.address.LastName || ''}`.trim()
112
+ : null,
113
+ company: customerResult.address?.Company || null,
114
+ phone: customerResult.address?.Phone || null,
115
+ orders: customerResult.orders.slice(0, 5),
116
+ totalOrders: customerResult.orders.length,
117
+ totalSpent: customerResult.orders.reduce((sum, o) => sum + (o.TotalCost || 0), 0),
118
+ } : null,
119
+ zendesk: {
120
+ tickets: tickets.slice(0, 5),
121
+ totalTickets: tickets.length,
122
+ openTickets: tickets.filter(t => ['new', 'open', 'pending'].includes(String(t.status))).length,
123
+ },
124
+ };
125
+ if (options.json) {
126
+ console.log(JSON.stringify(result, null, 2));
127
+ return;
128
+ }
129
+ console.log(`\n 👤 Customer 360: ${email}`);
130
+ console.log(" " + "═".repeat(60));
131
+ // Billbee section
132
+ if (result.billbee) {
133
+ console.log(`\n 📦 ORDERS (Billbee)`);
134
+ console.log(" " + "─".repeat(40));
135
+ if (result.billbee.name)
136
+ console.log(` Name: ${result.billbee.name}`);
137
+ if (result.billbee.company)
138
+ console.log(` Company: ${result.billbee.company}`);
139
+ if (result.billbee.phone)
140
+ console.log(` Phone: ${result.billbee.phone}`);
141
+ console.log(` Total: ${result.billbee.totalOrders} orders | €${result.billbee.totalSpent.toFixed(2)}`);
142
+ if (result.billbee.orders.length > 0) {
143
+ console.log(`\n Recent orders:`);
144
+ for (const order of result.billbee.orders) {
145
+ const date = order.CreatedAt ? new Date(order.CreatedAt).toLocaleDateString("de-DE") : "?";
146
+ console.log(` #${(order.OrderNumber || "?").padEnd(12)} │ ${date} │ €${(order.TotalCost || 0).toFixed(2)}`);
147
+ }
148
+ }
149
+ }
150
+ else {
151
+ console.log(`\n 📦 ORDERS: No Billbee data found`);
152
+ }
153
+ // Zendesk section
154
+ console.log(`\n 🎫 TICKETS (Zendesk)`);
155
+ console.log(" " + "─".repeat(40));
156
+ console.log(` Total: ${result.zendesk.totalTickets} tickets | ${result.zendesk.openTickets} open`);
157
+ if (result.zendesk.tickets.length > 0) {
158
+ console.log(`\n Recent tickets:`);
159
+ for (const ticket of result.zendesk.tickets) {
160
+ const statusIcon = getStatusIcon(String(ticket.status));
161
+ console.log(` ${statusIcon} #${String(ticket.id).padEnd(8)} │ ${String(ticket.status).padEnd(8)} │ ${String(ticket.subject).slice(0, 35)}`);
162
+ }
163
+ }
164
+ console.log("");
165
+ }
166
+ catch (error) {
167
+ console.error("Error:", error.message);
168
+ process.exit(1);
169
+ }
170
+ });
171
+ function getStatusIcon(status) {
172
+ switch (status) {
173
+ case "new": return "🆕";
174
+ case "open": return "📬";
175
+ case "pending": return "⏳";
176
+ case "solved": return "✅";
177
+ case "closed": return "🔒";
178
+ default: return "○";
179
+ }
180
+ }
181
+ export default customersCommand;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Husky Biz Orders Command
3
+ *
4
+ * Manages orders via Billbee API
5
+ */
6
+ import { Command } from "commander";
7
+ export declare const ordersCommand: Command;
8
+ export default ordersCommand;
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Husky Biz Orders Command
3
+ *
4
+ * Manages orders via Billbee API
5
+ */
6
+ import { Command } from "commander";
7
+ import { BillbeeClient, OrderStateLabels } from "../../lib/biz/index.js";
8
+ export const ordersCommand = new Command("orders")
9
+ .description("Manage orders (Billbee)");
10
+ // husky biz orders list
11
+ ordersCommand
12
+ .command("list")
13
+ .description("List orders")
14
+ .option("-s, --status <status>", "Filter by status (ordered, paid, shipped, completed, etc.)")
15
+ .option("-l, --limit <num>", "Number of orders to show", "20")
16
+ .option("-p, --page <num>", "Page number", "1")
17
+ .option("--json", "Output as JSON")
18
+ .action(async (options) => {
19
+ try {
20
+ const client = BillbeeClient.fromConfig();
21
+ // Map status string to state ID
22
+ let orderStateId;
23
+ if (options.status) {
24
+ const statusLower = options.status.toLowerCase();
25
+ const stateEntry = Object.entries(OrderStateLabels).find(([, label]) => label === statusLower);
26
+ if (stateEntry) {
27
+ orderStateId = [parseInt(stateEntry[0], 10)];
28
+ }
29
+ else {
30
+ console.error(`Unknown status: ${options.status}`);
31
+ console.error("Available: ordered, paid, shipped, completed, cancelled, return, packing, ready");
32
+ process.exit(1);
33
+ }
34
+ }
35
+ const response = await client.listOrders({
36
+ page: parseInt(options.page, 10),
37
+ pageSize: parseInt(options.limit, 10),
38
+ orderStateId,
39
+ includePositions: true,
40
+ });
41
+ if (options.json) {
42
+ console.log(JSON.stringify(response, null, 2));
43
+ return;
44
+ }
45
+ console.log(`\n 📦 Orders (${response.Paging.TotalRows} total)\n`);
46
+ if (response.Data.length === 0) {
47
+ console.log(" No orders found.");
48
+ return;
49
+ }
50
+ for (const order of response.Data) {
51
+ const stateLabel = OrderStateLabels[order.State || 0] || "unknown";
52
+ const date = order.CreatedAt ? new Date(order.CreatedAt).toLocaleDateString("de-DE") : "?";
53
+ const customer = order.InvoiceAddress?.LastName || order.Buyer?.Email || "Unknown";
54
+ const total = order.TotalCost?.toFixed(2) || "0.00";
55
+ console.log(` #${order.OrderNumber?.padEnd(12)} │ ${stateLabel.padEnd(10)} │ ${date} │ ${customer.slice(0, 20).padEnd(20)} │ €${total}`);
56
+ }
57
+ console.log(`\n Page ${response.Paging.Page} of ${response.Paging.TotalPages}\n`);
58
+ }
59
+ catch (error) {
60
+ console.error("Error:", error.message);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ // husky biz orders get <id>
65
+ ordersCommand
66
+ .command("get <id>")
67
+ .description("Get order details")
68
+ .option("--json", "Output as JSON")
69
+ .action(async (id, options) => {
70
+ try {
71
+ const client = BillbeeClient.fromConfig();
72
+ const response = await client.getOrder(id);
73
+ const order = response.Data;
74
+ if (options.json) {
75
+ console.log(JSON.stringify(order, null, 2));
76
+ return;
77
+ }
78
+ const stateLabel = OrderStateLabels[order.State || 0] || "unknown";
79
+ console.log(`\n Order #${order.OrderNumber}`);
80
+ console.log(" " + "─".repeat(50));
81
+ console.log(` Billbee ID: ${order.BillbeeId || order.Id}`);
82
+ console.log(` Status: ${stateLabel}`);
83
+ console.log(` Created: ${order.CreatedAt ? new Date(order.CreatedAt).toLocaleString("de-DE") : "?"}`);
84
+ console.log(` Total: €${order.TotalCost?.toFixed(2) || "0.00"}`);
85
+ console.log(` Shipping: €${order.ShippingCost?.toFixed(2) || "0.00"}`);
86
+ if (order.InvoiceNumber) {
87
+ console.log(` Invoice: ${order.InvoiceNumber}`);
88
+ }
89
+ // Customer
90
+ const addr = order.InvoiceAddress;
91
+ if (addr) {
92
+ console.log(`\n Customer:`);
93
+ console.log(` ${addr.FirstName || ""} ${addr.LastName || ""}`);
94
+ if (addr.Company)
95
+ console.log(` ${addr.Company}`);
96
+ console.log(` ${addr.Street || ""} ${addr.HouseNumber || ""}`);
97
+ console.log(` ${addr.Zip || ""} ${addr.City || ""}`);
98
+ if (addr.Email)
99
+ console.log(` ${addr.Email}`);
100
+ }
101
+ // Items
102
+ if (order.OrderItems && order.OrderItems.length > 0) {
103
+ console.log(`\n Items:`);
104
+ for (const item of order.OrderItems) {
105
+ const sku = item.Product?.SKU || "-";
106
+ const title = item.Product?.Title?.slice(0, 35) || "Unknown";
107
+ console.log(` ${item.Quantity}x ${sku.padEnd(15)} ${title} (€${item.TotalPrice.toFixed(2)})`);
108
+ }
109
+ }
110
+ console.log("");
111
+ }
112
+ catch (error) {
113
+ console.error("Error:", error.message);
114
+ process.exit(1);
115
+ }
116
+ });
117
+ // husky biz orders invoice <id>
118
+ ordersCommand
119
+ .command("invoice <id>")
120
+ .description("Get invoice info for order")
121
+ .action(async (id) => {
122
+ try {
123
+ const client = BillbeeClient.fromConfig();
124
+ const response = await client.getOrder(id);
125
+ const order = response.Data;
126
+ if (order.InvoiceNumber) {
127
+ console.log(`\n Invoice: ${order.InvoiceNumber}`);
128
+ if (order.InvoiceDate) {
129
+ console.log(` Date: ${new Date(order.InvoiceDate).toLocaleDateString("de-DE")}`);
130
+ }
131
+ console.log(` Total: €${order.TotalCost?.toFixed(2) || "0.00"}`);
132
+ }
133
+ else {
134
+ console.log("\n No invoice generated for this order.");
135
+ }
136
+ console.log("");
137
+ }
138
+ catch (error) {
139
+ console.error("Error:", error.message);
140
+ process.exit(1);
141
+ }
142
+ });
143
+ // husky biz orders update <id>
144
+ ordersCommand
145
+ .command("update <id>")
146
+ .description("Update order properties")
147
+ .option("--state <state>", "New state (paid, shipped, completed, etc.)")
148
+ .option("--comment <text>", "Add seller comment")
149
+ .action(async (id, options) => {
150
+ try {
151
+ const client = BillbeeClient.fromConfig();
152
+ const updates = {};
153
+ if (options.state) {
154
+ const stateEntry = Object.entries(OrderStateLabels).find(([, label]) => label === options.state.toLowerCase());
155
+ if (stateEntry) {
156
+ updates.State = parseInt(stateEntry[0], 10);
157
+ }
158
+ else {
159
+ console.error(`Unknown state: ${options.state}`);
160
+ process.exit(1);
161
+ }
162
+ }
163
+ if (options.comment) {
164
+ updates.SellerComment = options.comment;
165
+ }
166
+ if (Object.keys(updates).length === 0) {
167
+ console.error("Error: Provide --state or --comment");
168
+ process.exit(1);
169
+ }
170
+ const response = await client.updateOrder(id, updates);
171
+ console.log(`✓ Order #${response.Data.OrderNumber} updated`);
172
+ }
173
+ catch (error) {
174
+ console.error("Error:", error.message);
175
+ process.exit(1);
176
+ }
177
+ });
178
+ // husky biz orders add-tag <id> <tag>
179
+ ordersCommand
180
+ .command("add-tag <id> <tag>")
181
+ .description("Add a tag to an order")
182
+ .action(async (id, tag) => {
183
+ try {
184
+ const client = BillbeeClient.fromConfig();
185
+ await client.addOrderTags(parseInt(id, 10), [tag]);
186
+ console.log(`✓ Tag "${tag}" added to order #${id}`);
187
+ }
188
+ catch (error) {
189
+ console.error("Error:", error.message);
190
+ process.exit(1);
191
+ }
192
+ });
193
+ // husky biz orders remove-tag <id> <tag>
194
+ ordersCommand
195
+ .command("remove-tag <id> <tag>")
196
+ .description("Remove a tag from an order")
197
+ .action(async (id, tag) => {
198
+ try {
199
+ const client = BillbeeClient.fromConfig();
200
+ await client.removeOrderTags(parseInt(id, 10), [tag]);
201
+ console.log(`✓ Tag "${tag}" removed from order #${id}`);
202
+ }
203
+ catch (error) {
204
+ console.error("Error:", error.message);
205
+ process.exit(1);
206
+ }
207
+ });
208
+ // husky biz orders note <id>
209
+ ordersCommand
210
+ .command("note <id>")
211
+ .description("Add seller comment/note to order")
212
+ .requiredOption("-m, --message <text>", "Note content")
213
+ .action(async (id, options) => {
214
+ try {
215
+ const client = BillbeeClient.fromConfig();
216
+ await client.updateOrder(id, {
217
+ SellerComment: options.message,
218
+ });
219
+ console.log(`✓ Note added to order #${id}`);
220
+ }
221
+ catch (error) {
222
+ console.error("Error:", error.message);
223
+ process.exit(1);
224
+ }
225
+ });
226
+ export default ordersCommand;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Husky Biz Products Command
3
+ *
4
+ * Manages products via Billbee API
5
+ */
6
+ import { Command } from "commander";
7
+ export declare const productsCommand: Command;
8
+ export default productsCommand;