@simonfestl/husky-cli 1.10.0 → 1.13.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/README.md +126 -0
- package/dist/commands/auth.js +176 -1
- package/dist/commands/biz/emove.d.ts +12 -0
- package/dist/commands/biz/emove.js +249 -0
- package/dist/commands/biz/skuterzone.d.ts +12 -0
- package/dist/commands/biz/skuterzone.js +248 -0
- package/dist/commands/biz/wattiz.d.ts +12 -0
- package/dist/commands/biz/wattiz.js +252 -0
- package/dist/commands/biz.js +7 -1
- package/dist/commands/config.d.ts +28 -0
- package/dist/commands/config.js +45 -2
- package/dist/commands/task.js +4 -2
- package/dist/index.js +2 -0
- package/dist/lib/api-client.d.ts +13 -0
- package/dist/lib/api-client.js +117 -0
- package/dist/lib/biz/emove-playwright.d.ts +22 -0
- package/dist/lib/biz/emove-playwright.js +289 -0
- package/dist/lib/biz/emove-types.d.ts +60 -0
- package/dist/lib/biz/emove-types.js +7 -0
- package/dist/lib/biz/skuterzone-playwright.d.ts +21 -0
- package/dist/lib/biz/skuterzone-playwright.js +271 -0
- package/dist/lib/biz/skuterzone-types.d.ts +60 -0
- package/dist/lib/biz/skuterzone-types.js +7 -0
- package/dist/lib/biz/sop.js +1 -14
- package/dist/lib/biz/wattiz-playwright.d.ts +22 -0
- package/dist/lib/biz/wattiz-playwright.js +380 -0
- package/dist/lib/biz/wattiz-types.d.ts +61 -0
- package/dist/lib/biz/wattiz-types.js +6 -0
- package/package.json +2 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Skuterzone Command
|
|
3
|
+
*
|
|
4
|
+
* Manages skuterzonepro.com (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* WooCommerce platform integration
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import { SkuterzonePlaywrightClient } from "../../lib/biz/skuterzone-playwright.js";
|
|
12
|
+
import { getConfig, saveConfig } from "../config.js";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
export const skuterzoneCommand = new Command("skuterzone")
|
|
16
|
+
.description("Manage skuterzonepro.com (e-mobility parts supplier - WooCommerce)");
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// husky biz skuterzone login
|
|
19
|
+
// ============================================================================
|
|
20
|
+
skuterzoneCommand
|
|
21
|
+
.command("login")
|
|
22
|
+
.description("Setup Skuterzone credentials")
|
|
23
|
+
.requiredOption("-u, --username <username>", "Login username or email")
|
|
24
|
+
.requiredOption("-p, --password <password>", "Login password")
|
|
25
|
+
.option("--base-url <url>", "Base URL", "https://skuterzonepro.com")
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
try {
|
|
28
|
+
// Save to config
|
|
29
|
+
const config = getConfig();
|
|
30
|
+
config.skuterzoneUsername = options.username;
|
|
31
|
+
config.skuterzonePassword = options.password;
|
|
32
|
+
if (options.baseUrl) {
|
|
33
|
+
config.skuterzoneBaseUrl = options.baseUrl;
|
|
34
|
+
}
|
|
35
|
+
saveConfig(config);
|
|
36
|
+
console.log("Testing authentication...");
|
|
37
|
+
// Test login
|
|
38
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
39
|
+
try {
|
|
40
|
+
const result = await client.login();
|
|
41
|
+
if (result.success) {
|
|
42
|
+
console.log("✓ Successfully authenticated with skuterzonepro.com");
|
|
43
|
+
console.log("\nYou can now use:");
|
|
44
|
+
console.log(" husky biz skuterzone orders list");
|
|
45
|
+
console.log(" husky biz skuterzone orders get <id>");
|
|
46
|
+
console.log(" husky biz skuterzone invoice <order-id>");
|
|
47
|
+
console.log(" husky biz skuterzone products <query>");
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.error("✗ Login failed:", result.error);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await client.close();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error("✗ Login failed:", error.message);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// husky biz skuterzone orders
|
|
65
|
+
// ============================================================================
|
|
66
|
+
const ordersSubcommand = new Command("orders")
|
|
67
|
+
.description("View supplier orders");
|
|
68
|
+
ordersSubcommand
|
|
69
|
+
.command("list")
|
|
70
|
+
.description("List all orders from Skuterzone")
|
|
71
|
+
.option("--json", "Output as JSON")
|
|
72
|
+
.action(async (options) => {
|
|
73
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
74
|
+
try {
|
|
75
|
+
const orders = await client.listOrders();
|
|
76
|
+
if (options.json) {
|
|
77
|
+
console.log(JSON.stringify(orders, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (orders.length === 0) {
|
|
81
|
+
console.log("\n No orders found.\n");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(`\n 📦 Skuterzone Orders (${orders.length} found)\n`);
|
|
85
|
+
// Header
|
|
86
|
+
console.log(` ${"Order #".padEnd(15)} │ ` +
|
|
87
|
+
`${"Date".padEnd(20)} │ ` +
|
|
88
|
+
`${"Status".padEnd(15)} │ ` +
|
|
89
|
+
`${"Total".padEnd(12)}`);
|
|
90
|
+
console.log(" " + "─".repeat(75));
|
|
91
|
+
// Orders
|
|
92
|
+
for (const order of orders) {
|
|
93
|
+
console.log(` ${order.orderNumber.padEnd(15)} │ ` +
|
|
94
|
+
`${order.date.padEnd(20)} │ ` +
|
|
95
|
+
`${order.status.padEnd(15)} │ ` +
|
|
96
|
+
`${order.total}`);
|
|
97
|
+
}
|
|
98
|
+
console.log("");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("Error:", error.message);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
await client.close();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
ordersSubcommand
|
|
109
|
+
.command("get <id>")
|
|
110
|
+
.description("Get order details")
|
|
111
|
+
.option("--json", "Output as JSON")
|
|
112
|
+
.action(async (id, options) => {
|
|
113
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
114
|
+
try {
|
|
115
|
+
const order = await client.getOrder(id);
|
|
116
|
+
if (options.json) {
|
|
117
|
+
console.log(JSON.stringify(order, null, 2));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log(`\n Order ${order.orderNumber}`);
|
|
121
|
+
console.log(" " + "─".repeat(60));
|
|
122
|
+
console.log(` Status: ${order.status}`);
|
|
123
|
+
console.log(` Date: ${order.date}`);
|
|
124
|
+
console.log(` Total: ${order.total}`);
|
|
125
|
+
if (order.trackingNumber) {
|
|
126
|
+
console.log(` Tracking: ${order.trackingNumber}`);
|
|
127
|
+
}
|
|
128
|
+
if (order.paymentMethod) {
|
|
129
|
+
console.log(` Payment: ${order.paymentMethod}`);
|
|
130
|
+
}
|
|
131
|
+
if (order.customer && order.customer.name) {
|
|
132
|
+
console.log(`\n Shipping To:`);
|
|
133
|
+
console.log(` ${order.customer.name}`);
|
|
134
|
+
if (order.customer.company) {
|
|
135
|
+
console.log(` ${order.customer.company}`);
|
|
136
|
+
}
|
|
137
|
+
if (order.customer.address) {
|
|
138
|
+
console.log(` ${order.customer.address}`);
|
|
139
|
+
}
|
|
140
|
+
if (order.customer.postcode && order.customer.city) {
|
|
141
|
+
console.log(` ${order.customer.postcode} ${order.customer.city}`);
|
|
142
|
+
}
|
|
143
|
+
if (order.customer.email) {
|
|
144
|
+
console.log(` ${order.customer.email}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (order.items.length > 0) {
|
|
148
|
+
console.log(`\n Items:`);
|
|
149
|
+
for (const item of order.items) {
|
|
150
|
+
const sku = item.sku ? `[${item.sku}]`.padEnd(18) : "".padEnd(18);
|
|
151
|
+
const name = item.name.slice(0, 35).padEnd(35);
|
|
152
|
+
console.log(` ${item.quantity}x ${sku} ${name} (${item.total})`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (order.subtotal || order.shipping || order.tax) {
|
|
156
|
+
console.log(`\n Totals:`);
|
|
157
|
+
if (order.subtotal)
|
|
158
|
+
console.log(` Subtotal: ${order.subtotal}`);
|
|
159
|
+
if (order.shipping)
|
|
160
|
+
console.log(` Shipping: ${order.shipping}`);
|
|
161
|
+
if (order.tax)
|
|
162
|
+
console.log(` Tax: ${order.tax}`);
|
|
163
|
+
console.log(` Total: ${order.total}`);
|
|
164
|
+
}
|
|
165
|
+
if (order.invoiceUrl) {
|
|
166
|
+
console.log(`\n 📄 Invoice available`);
|
|
167
|
+
console.log(` Download with: husky biz skuterzone invoice ${order.id}`);
|
|
168
|
+
}
|
|
169
|
+
console.log("");
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error("Error:", error.message);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
await client.close();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
skuterzoneCommand.addCommand(ordersSubcommand);
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// husky biz skuterzone invoice
|
|
182
|
+
// ============================================================================
|
|
183
|
+
skuterzoneCommand
|
|
184
|
+
.command("invoice <order-id>")
|
|
185
|
+
.description("Download invoice PDF for order")
|
|
186
|
+
.option("-o, --output <path>", "Save path (default: ~/Downloads/skuterzone-invoice-{id}.pdf)")
|
|
187
|
+
.action(async (orderId, options) => {
|
|
188
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
189
|
+
try {
|
|
190
|
+
const savePath = options.output ||
|
|
191
|
+
path.join(homedir(), 'Downloads', `skuterzone-invoice-${orderId}.pdf`);
|
|
192
|
+
console.log(`Downloading invoice for order #${orderId}...`);
|
|
193
|
+
const success = await client.downloadInvoice(orderId, savePath);
|
|
194
|
+
if (success) {
|
|
195
|
+
console.log(`✓ Invoice saved to: ${savePath}`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.error("✗ Invoice not available for this order");
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
console.error("Error:", error.message);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
await client.close();
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// husky biz skuterzone products
|
|
212
|
+
// ============================================================================
|
|
213
|
+
skuterzoneCommand
|
|
214
|
+
.command("products <query>")
|
|
215
|
+
.description("Search for parts in catalog")
|
|
216
|
+
.option("--json", "Output as JSON")
|
|
217
|
+
.action(async (query, options) => {
|
|
218
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
219
|
+
try {
|
|
220
|
+
const products = await client.searchProducts(query);
|
|
221
|
+
if (options.json) {
|
|
222
|
+
console.log(JSON.stringify(products, null, 2));
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (products.length === 0) {
|
|
226
|
+
console.log(`\n No products found for: "${query}"\n`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
console.log(`\n 🔍 Search results for: "${query}" (${products.length} found)\n`);
|
|
230
|
+
for (const product of products) {
|
|
231
|
+
const sku = product.sku ? `[${product.sku}]` : '';
|
|
232
|
+
const price = product.price || 'Price hidden (login required)';
|
|
233
|
+
const stock = product.stockStatus || '';
|
|
234
|
+
console.log(` ${product.name}`);
|
|
235
|
+
console.log(` ${sku} ${price}${stock ? ' - ' + stock : ''}`);
|
|
236
|
+
console.log(` ${product.url}`);
|
|
237
|
+
console.log("");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
console.error("Error:", error.message);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
await client.close();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
export default skuterzoneCommand;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Wattiz Command
|
|
3
|
+
*
|
|
4
|
+
* Manages wattiz.fr (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* PrestaShop platform integration
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
export declare const wattizCommand: Command;
|
|
12
|
+
export default wattizCommand;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Wattiz Command
|
|
3
|
+
*
|
|
4
|
+
* Manages wattiz.fr (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* PrestaShop platform integration
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import { WattizPlaywrightClient } from "../../lib/biz/wattiz-playwright.js";
|
|
12
|
+
import { getConfig, saveConfig } from "../config.js";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
export const wattizCommand = new Command("wattiz")
|
|
16
|
+
.description("Manage wattiz.fr (e-mobility parts supplier - PrestaShop)");
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// husky biz wattiz login
|
|
19
|
+
// ============================================================================
|
|
20
|
+
wattizCommand
|
|
21
|
+
.command("login")
|
|
22
|
+
.description("Setup Wattiz credentials")
|
|
23
|
+
.requiredOption("-u, --username <username>", "Login username or email")
|
|
24
|
+
.requiredOption("-p, --password <password>", "Login password")
|
|
25
|
+
.option("--base-url <url>", "Base URL", "https://www.wattiz.fr")
|
|
26
|
+
.option("--language <lang>", "Language (gb, fr, de, es)", "gb")
|
|
27
|
+
.action(async (options) => {
|
|
28
|
+
try {
|
|
29
|
+
// Save to config
|
|
30
|
+
const config = getConfig();
|
|
31
|
+
config.wattizUsername = options.username;
|
|
32
|
+
config.wattizPassword = options.password;
|
|
33
|
+
if (options.baseUrl) {
|
|
34
|
+
config.wattizBaseUrl = options.baseUrl;
|
|
35
|
+
}
|
|
36
|
+
if (options.language) {
|
|
37
|
+
config.wattizLanguage = options.language;
|
|
38
|
+
}
|
|
39
|
+
saveConfig(config);
|
|
40
|
+
console.log("Testing authentication...");
|
|
41
|
+
// Test login
|
|
42
|
+
const client = WattizPlaywrightClient.fromConfig();
|
|
43
|
+
try {
|
|
44
|
+
const result = await client.login();
|
|
45
|
+
if (result.success) {
|
|
46
|
+
console.log("✓ Successfully authenticated with wattiz.fr");
|
|
47
|
+
console.log("\nYou can now use:");
|
|
48
|
+
console.log(" husky biz wattiz orders list");
|
|
49
|
+
console.log(" husky biz wattiz orders get <id>");
|
|
50
|
+
console.log(" husky biz wattiz invoice <order-id>");
|
|
51
|
+
console.log(" husky biz wattiz products <query>");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.error("✗ Login failed:", result.error);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await client.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error("✗ Login failed:", error.message);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// husky biz wattiz orders
|
|
69
|
+
// ============================================================================
|
|
70
|
+
const ordersSubcommand = new Command("orders")
|
|
71
|
+
.description("View supplier orders");
|
|
72
|
+
ordersSubcommand
|
|
73
|
+
.command("list")
|
|
74
|
+
.description("List all orders from Wattiz")
|
|
75
|
+
.option("--json", "Output as JSON")
|
|
76
|
+
.action(async (options) => {
|
|
77
|
+
const client = WattizPlaywrightClient.fromConfig();
|
|
78
|
+
try {
|
|
79
|
+
const orders = await client.listOrders();
|
|
80
|
+
if (options.json) {
|
|
81
|
+
console.log(JSON.stringify(orders, null, 2));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (orders.length === 0) {
|
|
85
|
+
console.log("\n No orders found.\n");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
console.log(`\n 📦 Wattiz Orders (${orders.length} found)\n`);
|
|
89
|
+
// Header
|
|
90
|
+
console.log(` ${"Order #".padEnd(15)} │ ` +
|
|
91
|
+
`${"Date".padEnd(20)} │ ` +
|
|
92
|
+
`${"Status".padEnd(15)} │ ` +
|
|
93
|
+
`${"Total".padEnd(12)}`);
|
|
94
|
+
console.log(" " + "─".repeat(75));
|
|
95
|
+
// Orders
|
|
96
|
+
for (const order of orders) {
|
|
97
|
+
console.log(` ${order.orderNumber.padEnd(15)} │ ` +
|
|
98
|
+
`${order.date.padEnd(20)} │ ` +
|
|
99
|
+
`${order.status.padEnd(15)} │ ` +
|
|
100
|
+
`${order.total}`);
|
|
101
|
+
}
|
|
102
|
+
console.log("");
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error("Error:", error.message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
await client.close();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
ordersSubcommand
|
|
113
|
+
.command("get <id>")
|
|
114
|
+
.description("Get order details")
|
|
115
|
+
.option("--json", "Output as JSON")
|
|
116
|
+
.action(async (id, options) => {
|
|
117
|
+
const client = WattizPlaywrightClient.fromConfig();
|
|
118
|
+
try {
|
|
119
|
+
const order = await client.getOrder(id);
|
|
120
|
+
if (options.json) {
|
|
121
|
+
console.log(JSON.stringify(order, null, 2));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
console.log(`\n Order ${order.orderNumber}`);
|
|
125
|
+
console.log(" " + "─".repeat(60));
|
|
126
|
+
console.log(` Status: ${order.status}`);
|
|
127
|
+
console.log(` Date: ${order.date}`);
|
|
128
|
+
console.log(` Total: ${order.total}`);
|
|
129
|
+
if (order.trackingNumber) {
|
|
130
|
+
console.log(` Tracking: ${order.trackingNumber}`);
|
|
131
|
+
}
|
|
132
|
+
if (order.paymentMethod) {
|
|
133
|
+
console.log(` Payment: ${order.paymentMethod}`);
|
|
134
|
+
}
|
|
135
|
+
if (order.customer && order.customer.name) {
|
|
136
|
+
console.log(`\n Shipping To:`);
|
|
137
|
+
console.log(` ${order.customer.name}`);
|
|
138
|
+
if (order.customer.company) {
|
|
139
|
+
console.log(` ${order.customer.company}`);
|
|
140
|
+
}
|
|
141
|
+
if (order.customer.address) {
|
|
142
|
+
console.log(` ${order.customer.address}`);
|
|
143
|
+
}
|
|
144
|
+
if (order.customer.postcode && order.customer.city) {
|
|
145
|
+
console.log(` ${order.customer.postcode} ${order.customer.city}`);
|
|
146
|
+
}
|
|
147
|
+
if (order.customer.email) {
|
|
148
|
+
console.log(` ${order.customer.email}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (order.items.length > 0) {
|
|
152
|
+
console.log(`\n Items:`);
|
|
153
|
+
for (const item of order.items) {
|
|
154
|
+
const sku = item.sku ? `[${item.sku}]`.padEnd(18) : "".padEnd(18);
|
|
155
|
+
const name = item.name.slice(0, 35).padEnd(35);
|
|
156
|
+
console.log(` ${item.quantity}x ${sku} ${name} (${item.total})`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (order.subtotal || order.shipping || order.tax) {
|
|
160
|
+
console.log(`\n Totals:`);
|
|
161
|
+
if (order.subtotal)
|
|
162
|
+
console.log(` Subtotal: ${order.subtotal}`);
|
|
163
|
+
if (order.shipping)
|
|
164
|
+
console.log(` Shipping: ${order.shipping}`);
|
|
165
|
+
if (order.tax)
|
|
166
|
+
console.log(` Tax: ${order.tax}`);
|
|
167
|
+
console.log(` Total: ${order.total}`);
|
|
168
|
+
}
|
|
169
|
+
if (order.invoiceUrl) {
|
|
170
|
+
console.log(`\n 📄 Invoice available`);
|
|
171
|
+
console.log(` Download with: husky biz wattiz invoice ${order.id}`);
|
|
172
|
+
}
|
|
173
|
+
console.log("");
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
console.error("Error:", error.message);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
await client.close();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
wattizCommand.addCommand(ordersSubcommand);
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// husky biz wattiz invoice
|
|
186
|
+
// ============================================================================
|
|
187
|
+
wattizCommand
|
|
188
|
+
.command("invoice <order-id>")
|
|
189
|
+
.description("Download invoice PDF for order")
|
|
190
|
+
.option("-o, --output <path>", "Save path (default: ~/Downloads/wattiz-invoice-{id}.pdf)")
|
|
191
|
+
.action(async (orderId, options) => {
|
|
192
|
+
const client = WattizPlaywrightClient.fromConfig();
|
|
193
|
+
try {
|
|
194
|
+
const savePath = options.output ||
|
|
195
|
+
path.join(homedir(), 'Downloads', `wattiz-invoice-${orderId}.pdf`);
|
|
196
|
+
console.log(`Downloading invoice for order #${orderId}...`);
|
|
197
|
+
const success = await client.downloadInvoice(orderId, savePath);
|
|
198
|
+
if (success) {
|
|
199
|
+
console.log(`✓ Invoice saved to: ${savePath}`);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.error("✗ Invoice not available for this order");
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
console.error("Error:", error.message);
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
await client.close();
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
// ============================================================================
|
|
215
|
+
// husky biz wattiz products
|
|
216
|
+
// ============================================================================
|
|
217
|
+
wattizCommand
|
|
218
|
+
.command("products <query>")
|
|
219
|
+
.description("Search for parts in catalog")
|
|
220
|
+
.option("--json", "Output as JSON")
|
|
221
|
+
.action(async (query, options) => {
|
|
222
|
+
const client = WattizPlaywrightClient.fromConfig();
|
|
223
|
+
try {
|
|
224
|
+
const products = await client.searchProducts(query);
|
|
225
|
+
if (options.json) {
|
|
226
|
+
console.log(JSON.stringify(products, null, 2));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (products.length === 0) {
|
|
230
|
+
console.log(`\n No products found for: "${query}"\n`);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
console.log(`\n 🔍 Search results for: "${query}" (${products.length} found)\n`);
|
|
234
|
+
for (const product of products) {
|
|
235
|
+
const sku = product.sku ? `[${product.sku}]` : '';
|
|
236
|
+
const price = product.price || 'Price hidden (login required)';
|
|
237
|
+
const stock = product.stockStatus || '';
|
|
238
|
+
console.log(` ${product.name}`);
|
|
239
|
+
console.log(` ${sku} ${price}${stock ? ' - ' + stock : ''}`);
|
|
240
|
+
console.log(` ${product.url}`);
|
|
241
|
+
console.log("");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error("Error:", error.message);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
await client.close();
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
export default wattizCommand;
|
package/dist/commands/biz.js
CHANGED
|
@@ -12,6 +12,9 @@ import { customersCommand } from "./biz/customers.js";
|
|
|
12
12
|
import { seatableCommand } from "./biz/seatable.js";
|
|
13
13
|
import { qdrantCommand } from "./biz/qdrant.js";
|
|
14
14
|
import { gotessCommand } from "./biz/gotess.js";
|
|
15
|
+
import { skuterzoneCommand } from "./biz/skuterzone.js";
|
|
16
|
+
import { emoveCommand } from "./biz/emove.js";
|
|
17
|
+
import { wattizCommand } from "./biz/wattiz.js";
|
|
15
18
|
import { guards } from "../lib/permissions.js";
|
|
16
19
|
export const bizCommand = new Command("biz")
|
|
17
20
|
.description("Business operations for autonomous agents")
|
|
@@ -22,5 +25,8 @@ export const bizCommand = new Command("biz")
|
|
|
22
25
|
.addCommand(customersCommand)
|
|
23
26
|
.addCommand(seatableCommand)
|
|
24
27
|
.addCommand(qdrantCommand)
|
|
25
|
-
.addCommand(gotessCommand)
|
|
28
|
+
.addCommand(gotessCommand)
|
|
29
|
+
.addCommand(skuterzoneCommand)
|
|
30
|
+
.addCommand(emoveCommand)
|
|
31
|
+
.addCommand(wattizCommand);
|
|
26
32
|
export default bizCommand;
|
|
@@ -3,6 +3,10 @@ type AgentRole = "supervisor" | "worker" | "reviewer" | "e2e_agent" | "pr_agent"
|
|
|
3
3
|
interface Config {
|
|
4
4
|
apiUrl?: string;
|
|
5
5
|
apiKey?: string;
|
|
6
|
+
sessionToken?: string;
|
|
7
|
+
sessionExpiresAt?: string;
|
|
8
|
+
sessionAgent?: string;
|
|
9
|
+
sessionRole?: string;
|
|
6
10
|
workerId?: string;
|
|
7
11
|
workerName?: string;
|
|
8
12
|
role?: AgentRole;
|
|
@@ -28,8 +32,19 @@ interface Config {
|
|
|
28
32
|
nocodbApiToken?: string;
|
|
29
33
|
nocodbBaseUrl?: string;
|
|
30
34
|
nocodbWorkspaceId?: string;
|
|
35
|
+
skuterzoneUsername?: string;
|
|
36
|
+
skuterzonePassword?: string;
|
|
37
|
+
skuterzoneBaseUrl?: string;
|
|
38
|
+
emoveUsername?: string;
|
|
39
|
+
emovePassword?: string;
|
|
40
|
+
emoveBaseUrl?: string;
|
|
41
|
+
wattizUsername?: string;
|
|
42
|
+
wattizPassword?: string;
|
|
43
|
+
wattizBaseUrl?: string;
|
|
44
|
+
wattizLanguage?: string;
|
|
31
45
|
}
|
|
32
46
|
export declare function getConfig(): Config;
|
|
47
|
+
export declare function saveConfig(config: Config): void;
|
|
33
48
|
/**
|
|
34
49
|
* Fetch role and permissions from /api/auth/whoami
|
|
35
50
|
* Caches the result in config for 1 hour
|
|
@@ -52,5 +67,18 @@ export declare function getRole(): AgentRole | undefined;
|
|
|
52
67
|
export declare function clearRoleCache(): void;
|
|
53
68
|
export declare function setConfig(key: "apiUrl" | "apiKey" | "workerId" | "workerName", value: string): void;
|
|
54
69
|
export declare function setGotessConfig(token: string, bookId: string): void;
|
|
70
|
+
export declare function setSessionConfig(session: {
|
|
71
|
+
token: string;
|
|
72
|
+
expiresAt: string;
|
|
73
|
+
agent: string;
|
|
74
|
+
role: string;
|
|
75
|
+
}): void;
|
|
76
|
+
export declare function clearSessionConfig(): void;
|
|
77
|
+
export declare function getSessionConfig(): {
|
|
78
|
+
token?: string;
|
|
79
|
+
expiresAt?: string;
|
|
80
|
+
agent?: string;
|
|
81
|
+
role?: string;
|
|
82
|
+
} | null;
|
|
55
83
|
export declare const configCommand: Command;
|
|
56
84
|
export {};
|
package/dist/commands/config.js
CHANGED
|
@@ -41,7 +41,7 @@ export function getConfig() {
|
|
|
41
41
|
return {};
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
function saveConfig(config) {
|
|
44
|
+
export function saveConfig(config) {
|
|
45
45
|
if (!existsSync(CONFIG_DIR)) {
|
|
46
46
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
47
47
|
}
|
|
@@ -127,6 +127,33 @@ export function setGotessConfig(token, bookId) {
|
|
|
127
127
|
config.gotessBookId = bookId;
|
|
128
128
|
saveConfig(config);
|
|
129
129
|
}
|
|
130
|
+
export function setSessionConfig(session) {
|
|
131
|
+
const config = getConfig();
|
|
132
|
+
config.sessionToken = session.token;
|
|
133
|
+
config.sessionExpiresAt = session.expiresAt;
|
|
134
|
+
config.sessionAgent = session.agent;
|
|
135
|
+
config.sessionRole = session.role;
|
|
136
|
+
saveConfig(config);
|
|
137
|
+
}
|
|
138
|
+
export function clearSessionConfig() {
|
|
139
|
+
const config = getConfig();
|
|
140
|
+
delete config.sessionToken;
|
|
141
|
+
delete config.sessionExpiresAt;
|
|
142
|
+
delete config.sessionAgent;
|
|
143
|
+
delete config.sessionRole;
|
|
144
|
+
saveConfig(config);
|
|
145
|
+
}
|
|
146
|
+
export function getSessionConfig() {
|
|
147
|
+
const config = getConfig();
|
|
148
|
+
if (!config.sessionToken)
|
|
149
|
+
return null;
|
|
150
|
+
return {
|
|
151
|
+
token: config.sessionToken,
|
|
152
|
+
expiresAt: config.sessionExpiresAt,
|
|
153
|
+
agent: config.sessionAgent,
|
|
154
|
+
role: config.sessionRole,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
130
157
|
export const configCommand = new Command("config")
|
|
131
158
|
.description("Manage CLI configuration");
|
|
132
159
|
// husky config set <key> <value>
|
|
@@ -166,6 +193,19 @@ configCommand
|
|
|
166
193
|
"nocodb-api-token": "nocodbApiToken",
|
|
167
194
|
"nocodb-base-url": "nocodbBaseUrl",
|
|
168
195
|
"nocodb-workspace-id": "nocodbWorkspaceId",
|
|
196
|
+
// Skuterzone
|
|
197
|
+
"skuterzone-username": "skuterzoneUsername",
|
|
198
|
+
"skuterzone-password": "skuterzonePassword",
|
|
199
|
+
"skuterzone-base-url": "skuterzoneBaseUrl",
|
|
200
|
+
// Emove Distribution
|
|
201
|
+
"emove-username": "emoveUsername",
|
|
202
|
+
"emove-password": "emovePassword",
|
|
203
|
+
"emove-base-url": "emoveBaseUrl",
|
|
204
|
+
// Wattiz
|
|
205
|
+
"wattiz-username": "wattizUsername",
|
|
206
|
+
"wattiz-password": "wattizPassword",
|
|
207
|
+
"wattiz-base-url": "wattizBaseUrl",
|
|
208
|
+
"wattiz-language": "wattizLanguage",
|
|
169
209
|
};
|
|
170
210
|
const configKey = keyMappings[key];
|
|
171
211
|
if (!configKey) {
|
|
@@ -180,6 +220,9 @@ configCommand
|
|
|
180
220
|
console.log(" Gotess: gotess-token, gotess-book-id");
|
|
181
221
|
console.log(" Gemini: gemini-api-key");
|
|
182
222
|
console.log(" NocoDB: nocodb-api-token, nocodb-base-url, nocodb-workspace-id");
|
|
223
|
+
console.log(" Skuterzone: skuterzone-username, skuterzone-password, skuterzone-base-url");
|
|
224
|
+
console.log(" Emove: emove-username, emove-password, emove-base-url");
|
|
225
|
+
console.log(" Wattiz: wattiz-username, wattiz-password, wattiz-base-url, wattiz-language");
|
|
183
226
|
console.log(" Brain: agent-type");
|
|
184
227
|
console.error("\n💡 For configuration help: husky explain config");
|
|
185
228
|
process.exit(1);
|
|
@@ -201,7 +244,7 @@ configCommand
|
|
|
201
244
|
config[configKey] = value;
|
|
202
245
|
saveConfig(config);
|
|
203
246
|
// Mask sensitive values in output
|
|
204
|
-
const sensitiveKeys = ["api-key", "billbee-api-key", "billbee-password", "zendesk-api-token", "seatable-api-token", "gotess-token", "gemini-api-key", "nocodb-api-token"];
|
|
247
|
+
const sensitiveKeys = ["api-key", "billbee-api-key", "billbee-password", "zendesk-api-token", "seatable-api-token", "gotess-token", "gemini-api-key", "nocodb-api-token", "skuterzone-username", "skuterzone-password", "emove-username", "emove-password", "wattiz-username", "wattiz-password"];
|
|
205
248
|
const displayValue = sensitiveKeys.includes(key) ? "***" : value;
|
|
206
249
|
console.log(`✓ Set ${key} = ${displayValue}`);
|
|
207
250
|
});
|
package/dist/commands/task.js
CHANGED
|
@@ -829,12 +829,14 @@ taskCommand
|
|
|
829
829
|
throw new Error(`API error: ${res.status}`);
|
|
830
830
|
}
|
|
831
831
|
const data = await res.json();
|
|
832
|
-
if (data.
|
|
832
|
+
if (data.approved === true && data.pending === false) {
|
|
833
833
|
console.log("✓ Plan approved!");
|
|
834
834
|
process.exit(0);
|
|
835
835
|
}
|
|
836
|
-
else if (data.
|
|
836
|
+
else if (data.approved === false && data.rejected === true) {
|
|
837
837
|
console.log("✗ Plan rejected");
|
|
838
|
+
if (data.reason)
|
|
839
|
+
console.log(`Reason: ${data.reason}`);
|
|
838
840
|
process.exit(1);
|
|
839
841
|
}
|
|
840
842
|
// Still pending, wait and poll again
|