incwo-cli 0.1.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.
@@ -0,0 +1,22 @@
1
+ export interface ColumnDef {
2
+ key: string;
3
+ label: string;
4
+ width?: number;
5
+ }
6
+ export interface ResourceDef {
7
+ /** CLI command name — matches the API endpoint */
8
+ command: string;
9
+ /** Short description */
10
+ description: string;
11
+ /** REST endpoint (always matches command) */
12
+ endpoint: string;
13
+ /** Columns to display in list output */
14
+ columns: ColumnDef[];
15
+ /** Fixed params appended to every list request */
16
+ defaultParams?: Record<string, string>;
17
+ /** Whether to expose --from / --to date filters */
18
+ hasDateFilter?: boolean;
19
+ /** Whether to expose --sheet-type filter (proposal_sheets only) */
20
+ hasSheetType?: boolean;
21
+ }
22
+ export declare const RESOURCES: ResourceDef[];
@@ -0,0 +1,497 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RESOURCES = void 0;
4
+ exports.RESOURCES = [
5
+ // ── CRM ──────────────────────────────────────────────────────────────────
6
+ {
7
+ command: 'contacts',
8
+ description: 'Contacts (people)',
9
+ endpoint: 'contacts',
10
+ columns: [
11
+ { key: 'id', label: 'ID', width: 8 },
12
+ { key: 'first_name', label: 'First name', width: 16 },
13
+ { key: 'last_name', label: 'Last name', width: 18 },
14
+ { key: 'firm_name', label: 'Company name', width: 24 },
15
+ { key: 'job_title', label: 'Job title', width: 22 },
16
+ { key: 'created_at', label: 'Created', width: 12 },
17
+ ],
18
+ },
19
+ {
20
+ command: 'firms',
21
+ description: 'Companies / organisations',
22
+ endpoint: 'firms',
23
+ columns: [
24
+ { key: 'id', label: 'ID', width: 8 },
25
+ { key: 'name', label: 'Name', width: 32 },
26
+ { key: 'siren', label: 'Siren', width: 14 },
27
+ { key: 'reference', label: 'Reference', width: 16 },
28
+ { key: 'created_at', label: 'Created', width: 12 },
29
+ ],
30
+ },
31
+ {
32
+ command: 'leads',
33
+ description: 'Sales opportunities',
34
+ endpoint: 'leads',
35
+ columns: [
36
+ { key: 'id', label: 'ID', width: 8 },
37
+ { key: 'reference', label: 'Reference', width: 16 },
38
+ { key: 'contact_id', label: 'Contact ID', width: 12 },
39
+ { key: 'firm_id', label: 'Firm ID', width: 10 },
40
+ { key: 'status_id', label: 'Status', width: 10 },
41
+ { key: 'step_id', label: 'Progress', width: 10 },
42
+ { key: 'value', label: 'Value', width: 12 },
43
+ { key: 'value_date', label: 'Est. sign. date', width: 14 },
44
+ { key: 'confidence_pct', label: 'Confidence %', width: 12 },
45
+ ],
46
+ hasDateFilter: true,
47
+ },
48
+ {
49
+ command: 'contact_items',
50
+ description: 'Contact details (emails, phones…)',
51
+ endpoint: 'contact_items',
52
+ columns: [
53
+ { key: 'id', label: 'ID', width: 8 },
54
+ { key: 'type_id', label: 'Type', width: 14 },
55
+ { key: 'value', label: 'Value', width: 34 },
56
+ { key: 'contact_id', label: 'Contact ID', width: 12 },
57
+ { key: 'is_default', label: 'Default', width: 8 },
58
+ ],
59
+ },
60
+ {
61
+ command: 'contact_addresses',
62
+ description: 'Contact addresses',
63
+ endpoint: 'contact_addresses',
64
+ columns: [
65
+ { key: 'id', label: 'ID', width: 8 },
66
+ { key: 'contact_id', label: 'Contact ID', width: 12 },
67
+ { key: 'street_address', label: 'Address', width: 30 },
68
+ { key: 'zip_code', label: 'ZIP', width: 8 },
69
+ { key: 'city', label: 'City', width: 18 },
70
+ { key: 'country', label: 'Country', width: 12 },
71
+ ],
72
+ },
73
+ {
74
+ command: 'contact_lists',
75
+ description: 'Contact lists',
76
+ endpoint: 'contact_lists',
77
+ columns: [
78
+ { key: 'id', label: 'ID', width: 8 },
79
+ { key: 'name', label: 'Name', width: 36 },
80
+ { key: 'description', label: 'Description', width: 30 },
81
+ { key: 'created_at', label: 'Created', width: 12 },
82
+ ],
83
+ },
84
+ {
85
+ command: 'missions',
86
+ description: 'Missions',
87
+ endpoint: 'missions',
88
+ columns: [
89
+ { key: 'id', label: 'ID', width: 8 },
90
+ { key: 'kind', label: 'Kind', width: 14 },
91
+ { key: 'title', label: 'Title', width: 32 },
92
+ { key: 'status_id', label: 'Status', width: 10 },
93
+ { key: 'progress', label: 'Progress', width: 12 },
94
+ { key: 'created_at', label: 'Created', width: 12 },
95
+ ],
96
+ },
97
+ // ── SALES ─────────────────────────────────────────────────────────────────
98
+ {
99
+ command: 'proposal_sheets',
100
+ description: 'Proposal sheets (quotes, orders, delivery notes…)',
101
+ endpoint: 'proposal_sheets',
102
+ hasSheetType: true,
103
+ columns: [
104
+ { key: 'id', label: 'ID', width: 8 },
105
+ { key: 'reference', label: 'Reference', width: 16 },
106
+ { key: 'sheet_type', label: 'Type', width: 14 },
107
+ { key: 'title', label: 'Title', width: 24 },
108
+ { key: 'billing_date', label: 'Billing date', width: 12 },
109
+ { key: 'firm_name', label: 'Company', width: 22 },
110
+ { key: 'vat_exl_total', label: 'Total excl. VAT', width: 14 },
111
+ { key: 'vat_inc_total', label: 'Total incl. VAT', width: 14 },
112
+ { key: 'status_id', label: 'Status', width: 10 },
113
+ { key: 'sent', label: 'Sent', width: 8 },
114
+ ],
115
+ hasDateFilter: true,
116
+ },
117
+ {
118
+ command: 'bill_sheets',
119
+ description: 'Customer invoices',
120
+ endpoint: 'bill_sheets',
121
+ columns: [
122
+ { key: 'id', label: 'ID', width: 8 },
123
+ { key: 'reference', label: 'Reference', width: 16 },
124
+ { key: 'sheet_type', label: 'Type', width: 12 },
125
+ { key: 'title', label: 'Title', width: 24 },
126
+ { key: 'billing_date', label: 'Billing date', width: 12 },
127
+ { key: 'firm_name', label: 'Company', width: 22 },
128
+ { key: 'vat_exl_total', label: 'Total excl. VAT', width: 14 },
129
+ { key: 'vat_inc_total', label: 'Total incl. VAT', width: 14 },
130
+ { key: 'payed_amount', label: 'Paid amount', width: 12 },
131
+ { key: 'sent', label: 'Sent', width: 8 },
132
+ ],
133
+ hasDateFilter: true,
134
+ },
135
+ {
136
+ command: 'emitted_payments',
137
+ description: 'Vendor bills / purchase invoices',
138
+ endpoint: 'emitted_payments',
139
+ columns: [
140
+ { key: 'id', label: 'ID', width: 8 },
141
+ { key: 'reference', label: 'Reference', width: 16 },
142
+ { key: 'kind', label: 'Kind', width: 12 },
143
+ { key: 'title', label: 'Title', width: 24 },
144
+ { key: 'payment_date', label: 'Payment date', width: 12 },
145
+ { key: 'amount', label: 'Amount', width: 12 },
146
+ { key: 'status_id', label: 'Status', width: 10 },
147
+ ],
148
+ hasDateFilter: true,
149
+ },
150
+ {
151
+ command: 'customer_products',
152
+ description: 'Product / service catalog',
153
+ endpoint: 'customer_products',
154
+ columns: [
155
+ { key: 'id', label: 'ID', width: 8 },
156
+ { key: 'reference', label: 'Ref.', width: 14 },
157
+ { key: 'name', label: 'Name', width: 30 },
158
+ { key: 'price', label: 'Price', width: 10 },
159
+ { key: 'unit', label: 'Unit', width: 8 },
160
+ { key: 'vat_id', label: 'VAT', width: 8 },
161
+ { key: 'is_active', label: 'Active', width: 8 },
162
+ ],
163
+ },
164
+ {
165
+ command: 'customer_product_categories',
166
+ description: 'Product categories',
167
+ endpoint: 'customer_product_categories',
168
+ columns: [
169
+ { key: 'id', label: 'ID', width: 8 },
170
+ { key: 'name', label: 'Name', width: 30 },
171
+ { key: 'parent_id', label: 'Parent ID', width: 10 },
172
+ { key: 'accounting_ref', label: 'Accounting ref', width: 16 },
173
+ { key: 'created_at', label: 'Created', width: 12 },
174
+ ],
175
+ },
176
+ {
177
+ command: 'customer_pricings',
178
+ description: 'Customer pricing rules',
179
+ endpoint: 'customer_pricings',
180
+ columns: [
181
+ { key: 'id', label: 'ID', width: 8 },
182
+ { key: 'customer_product_id', label: 'Product ID', width: 12 },
183
+ { key: 'name', label: 'Name', width: 26 },
184
+ { key: 'price_ht', label: 'Price excl. VAT', width: 14 },
185
+ { key: 'reduction_percent', label: 'Discount %', width: 12 },
186
+ { key: 'supplier_ref', label: 'Supplier ref', width: 16 },
187
+ ],
188
+ },
189
+ {
190
+ command: 'vendor_pricings',
191
+ description: 'Vendor pricing rules',
192
+ endpoint: 'vendor_pricings',
193
+ columns: [
194
+ { key: 'id', label: 'ID', width: 8 },
195
+ { key: 'customer_product_id', label: 'Product ID', width: 12 },
196
+ { key: 'name', label: 'Name', width: 26 },
197
+ { key: 'price_ht', label: 'Price excl. VAT', width: 14 },
198
+ { key: 'reduction_percent', label: 'Discount %', width: 12 },
199
+ { key: 'supplier_ref', label: 'Supplier ref', width: 16 },
200
+ ],
201
+ },
202
+ {
203
+ command: 'bank_accounts',
204
+ description: 'Bank accounts',
205
+ endpoint: 'bank_accounts',
206
+ columns: [
207
+ { key: 'id', label: 'ID', width: 8 },
208
+ { key: 'name', label: 'Name', width: 28 },
209
+ { key: 'city', label: 'City', width: 18 },
210
+ { key: 'accounting_ref', label: 'Accounting ref', width: 18 },
211
+ { key: 'created_at', label: 'Created', width: 12 },
212
+ ],
213
+ },
214
+ {
215
+ command: 'campaigns',
216
+ description: 'Marketing campaigns',
217
+ endpoint: 'campaigns',
218
+ columns: [
219
+ { key: 'id', label: 'ID', width: 8 },
220
+ { key: 'title', label: 'Title', width: 30 },
221
+ { key: 'reference', label: 'Reference', width: 16 },
222
+ { key: 'begins_at', label: 'Begins at', width: 12 },
223
+ { key: 'ends_at', label: 'Ends at', width: 12 },
224
+ ],
225
+ hasDateFilter: true,
226
+ },
227
+ // ── INVENTORY ─────────────────────────────────────────────────────────────
228
+ {
229
+ command: 'stock_movements',
230
+ description: 'Stock movements',
231
+ endpoint: 'stock_movements',
232
+ columns: [
233
+ { key: 'id', label: 'ID', width: 8 },
234
+ { key: 'customer_product_id', label: 'Product ID', width: 12 },
235
+ { key: 'direction', label: 'Direction', width: 10 },
236
+ { key: 'quantity', label: 'Qty', width: 8 },
237
+ { key: 'origin_warehouse_id', label: 'Origin WH', width: 12 },
238
+ { key: 'destination_warehouse_id', label: 'Dest. WH', width: 12 },
239
+ { key: 'moved_at', label: 'Moved at', width: 14 },
240
+ ],
241
+ hasDateFilter: true,
242
+ },
243
+ {
244
+ command: 'serial_numbers',
245
+ description: 'Serial numbers',
246
+ endpoint: 'serial_numbers',
247
+ columns: [
248
+ { key: 'id', label: 'ID', width: 8 },
249
+ { key: 'batch', label: 'Batch', width: 20 },
250
+ { key: 'barcode', label: 'Barcode', width: 18 },
251
+ { key: 'customer_product_id', label: 'Product ID', width: 12 },
252
+ { key: 'warehouse_id', label: 'Warehouse ID', width: 14 },
253
+ { key: 'quantity', label: 'Qty', width: 8 },
254
+ { key: 'moved_at', label: 'Moved at', width: 14 },
255
+ ],
256
+ },
257
+ {
258
+ command: 'serial_lots',
259
+ description: 'Serial lot numbers',
260
+ endpoint: 'serial_lots',
261
+ columns: [
262
+ { key: 'id', label: 'ID', width: 8 },
263
+ { key: 'batch', label: 'Batch', width: 20 },
264
+ { key: 'barcode', label: 'Barcode', width: 18 },
265
+ { key: 'customer_product_id', label: 'Product ID', width: 12 },
266
+ { key: 'warehouse_id', label: 'Warehouse ID', width: 14 },
267
+ { key: 'quantity', label: 'Qty', width: 8 },
268
+ { key: 'moved_at', label: 'Moved at', width: 14 },
269
+ ],
270
+ },
271
+ {
272
+ command: 'warehouses',
273
+ description: 'Warehouses / depots',
274
+ endpoint: 'warehouses',
275
+ columns: [
276
+ { key: 'id', label: 'ID', width: 8 },
277
+ { key: 'name', label: 'Name', width: 28 },
278
+ { key: 'city', label: 'City', width: 16 },
279
+ { key: 'zip_code', label: 'ZIP', width: 8 },
280
+ { key: 'country', label: 'Country', width: 12 },
281
+ { key: 'street_address', label: 'Address', width: 24 },
282
+ ],
283
+ },
284
+ // ── PROJECTS / TIME ───────────────────────────────────────────────────────
285
+ {
286
+ command: 'projects',
287
+ description: 'Projects',
288
+ endpoint: 'projects',
289
+ columns: [
290
+ { key: 'id', label: 'ID', width: 8 },
291
+ { key: 'name', label: 'Name', width: 28 },
292
+ { key: 'reference', label: 'Reference', width: 14 },
293
+ { key: 'status_id', label: 'Status', width: 10 },
294
+ { key: 'start_date', label: 'Start', width: 12 },
295
+ { key: 'end_date', label: 'End', width: 12 },
296
+ ],
297
+ hasDateFilter: true,
298
+ },
299
+ {
300
+ command: 'tasks',
301
+ description: 'Tasks',
302
+ endpoint: 'tasks',
303
+ columns: [
304
+ { key: 'id', label: 'ID', width: 8 },
305
+ { key: 'title', label: 'Title', width: 30 },
306
+ { key: 'status_id', label: 'Status', width: 10 },
307
+ { key: 'due_at', label: 'Due at', width: 12 },
308
+ { key: 'assigned_user_id', label: 'Assigned user', width: 14 },
309
+ { key: 'completion_percent', label: '% done', width: 8 },
310
+ ],
311
+ hasDateFilter: true,
312
+ },
313
+ {
314
+ command: 'timesheets',
315
+ description: 'Timesheets',
316
+ endpoint: 'timesheets',
317
+ columns: [
318
+ { key: 'id', label: 'ID', width: 8 },
319
+ { key: 'title', label: 'Title', width: 28 },
320
+ { key: 'period', label: 'Month', width: 10 },
321
+ { key: 'user_id', label: 'User ID', width: 10 },
322
+ { key: 'status_id', label: 'Status', width: 10 },
323
+ { key: 'sheet_type', label: 'Sheet type', width: 14 },
324
+ ],
325
+ hasDateFilter: true,
326
+ },
327
+ // ── HR ────────────────────────────────────────────────────────────────────
328
+ {
329
+ command: 'staff_members',
330
+ description: 'Staff members',
331
+ endpoint: 'staff_members',
332
+ columns: [
333
+ { key: 'id', label: 'ID', width: 8 },
334
+ { key: 'first_name', label: 'First name', width: 16 },
335
+ { key: 'last_name', label: 'Last name', width: 18 },
336
+ { key: 'job_label', label: 'Job', width: 20 },
337
+ { key: 'email', label: 'Email', width: 26 },
338
+ { key: 'status_id', label: 'Status', width: 10 },
339
+ ],
340
+ },
341
+ {
342
+ command: 'expense_sheets',
343
+ description: 'Expense reports',
344
+ endpoint: 'expense_sheets',
345
+ columns: [
346
+ { key: 'id', label: 'ID', width: 8 },
347
+ { key: 'staff_member_id', label: 'Staff member', width: 14 },
348
+ { key: 'period', label: 'Month', width: 10 },
349
+ { key: 'status_id', label: 'Status', width: 10 },
350
+ { key: 'payed_amount', label: 'Paid amount', width: 12 },
351
+ { key: 'submission_date', label: 'Submitted', width: 14 },
352
+ ],
353
+ hasDateFilter: true,
354
+ },
355
+ {
356
+ command: 'vacation_requests',
357
+ description: 'Vacation requests',
358
+ endpoint: 'vacation_requests',
359
+ columns: [
360
+ { key: 'id', label: 'ID', width: 8 },
361
+ { key: 'staff_member_id', label: 'Staff member', width: 14 },
362
+ { key: 'vacation_type_id', label: 'Type', width: 10 },
363
+ { key: 'start_date', label: 'Start', width: 14 },
364
+ { key: 'stop_date', label: 'End', width: 14 },
365
+ { key: 'duration', label: 'Duration', width: 10 },
366
+ { key: 'status_id', label: 'Status', width: 10 },
367
+ ],
368
+ hasDateFilter: true,
369
+ },
370
+ {
371
+ command: 'salary_campaigns',
372
+ description: 'Salary campaigns',
373
+ endpoint: 'salary_campaigns',
374
+ columns: [
375
+ { key: 'id', label: 'ID', width: 8 },
376
+ { key: 'period', label: 'Period', width: 14 },
377
+ { key: 'status_id', label: 'Status', width: 10 },
378
+ { key: 'created_at', label: 'Created', width: 12 },
379
+ ],
380
+ },
381
+ {
382
+ command: 'contracts',
383
+ description: 'Contracts',
384
+ endpoint: 'contracts',
385
+ columns: [
386
+ { key: 'id', label: 'ID', width: 8 },
387
+ { key: 'title', label: 'Title', width: 30 },
388
+ { key: 'reference', label: 'Reference', width: 16 },
389
+ { key: 'begin_date', label: 'Start', width: 12 },
390
+ { key: 'end_date', label: 'End', width: 12 },
391
+ { key: 'is_active', label: 'Active', width: 8 },
392
+ ],
393
+ hasDateFilter: true,
394
+ },
395
+ {
396
+ command: 'interviews',
397
+ description: 'HR interviews',
398
+ endpoint: 'interviews',
399
+ columns: [
400
+ { key: 'id', label: 'ID', width: 8 },
401
+ { key: 'job_candidate_id', label: 'Candidate ID', width: 14 },
402
+ { key: 'staff_member_id', label: 'Staff member', width: 14 },
403
+ { key: 'status_id', label: 'Status', width: 10 },
404
+ { key: 'comments', label: 'Comments', width: 30 },
405
+ { key: 'created_at', label: 'Created', width: 12 },
406
+ ],
407
+ hasDateFilter: true,
408
+ },
409
+ // ── MISC ──────────────────────────────────────────────────────────────────
410
+ {
411
+ command: 'notes',
412
+ description: 'Notes',
413
+ endpoint: 'notes',
414
+ columns: [
415
+ { key: 'id', label: 'ID', width: 8 },
416
+ { key: 'title', label: 'Title', width: 32 },
417
+ { key: 'type_id', label: 'Type', width: 10 },
418
+ { key: 'object_name', label: 'Support object', width: 16 },
419
+ { key: 'created_at', label: 'Created', width: 14 },
420
+ ],
421
+ hasDateFilter: true,
422
+ },
423
+ {
424
+ command: 'upload_files',
425
+ description: 'Files / attachments',
426
+ endpoint: 'upload_files',
427
+ columns: [
428
+ { key: 'id', label: 'ID', width: 8 },
429
+ { key: 'object_zname', label: 'Support object', width: 20 },
430
+ { key: 'object_zid', label: 'Object ID', width: 12 },
431
+ { key: 'shared_with_party', label: 'Shared', width: 8 },
432
+ { key: 'created_at', label: 'Created', width: 14 },
433
+ ],
434
+ hasDateFilter: true,
435
+ },
436
+ {
437
+ command: 'custom_labels',
438
+ description: 'Custom labels',
439
+ endpoint: 'custom_labels',
440
+ columns: [
441
+ { key: 'id', label: 'ID', width: 8 },
442
+ { key: 'label_type', label: 'Label type', width: 16 },
443
+ { key: 'long_label', label: 'Label', width: 28 },
444
+ { key: 'short_label', label: 'Short label', width: 16 },
445
+ { key: 'color', label: 'Color', width: 10 },
446
+ ],
447
+ },
448
+ {
449
+ command: 'conversations',
450
+ description: 'Conversations / messaging',
451
+ endpoint: 'conversations',
452
+ columns: [
453
+ { key: 'id', label: 'ID', width: 8 },
454
+ { key: 'title', label: 'Title', width: 34 },
455
+ { key: 'type_id', label: 'Type', width: 10 },
456
+ { key: 'status_id', label: 'Status', width: 10 },
457
+ { key: 'created_at', label: 'Created', width: 14 },
458
+ ],
459
+ hasDateFilter: true,
460
+ },
461
+ {
462
+ command: 'webhooks',
463
+ description: 'Configured webhooks',
464
+ endpoint: 'webhooks',
465
+ columns: [
466
+ { key: 'id', label: 'ID', width: 8 },
467
+ { key: 'object_zname', label: 'Object', width: 20 },
468
+ { key: 'object_zfield', label: 'Field', width: 20 },
469
+ { key: 'turl', label: 'URL', width: 36 },
470
+ { key: 'active', label: 'Active', width: 8 },
471
+ ],
472
+ },
473
+ {
474
+ command: 'bookables',
475
+ description: 'Bookable resources',
476
+ endpoint: 'bookables',
477
+ columns: [
478
+ { key: 'id', label: 'ID', width: 8 },
479
+ { key: 'kind', label: 'Kind', width: 16 },
480
+ { key: 'title', label: 'Title', width: 30 },
481
+ { key: 'price', label: 'Price', width: 12 },
482
+ { key: 'created_at', label: 'Created', width: 12 },
483
+ ],
484
+ },
485
+ {
486
+ command: 'fleets',
487
+ description: 'Vehicle fleets',
488
+ endpoint: 'fleets',
489
+ columns: [
490
+ { key: 'id', label: 'ID', width: 8 },
491
+ { key: 'kind', label: 'Kind', width: 16 },
492
+ { key: 'title', label: 'Title', width: 30 },
493
+ { key: 'contact_id', label: 'Contact ID', width: 12 },
494
+ { key: 'created_at', label: 'Created', width: 12 },
495
+ ],
496
+ },
497
+ ];
package/dist/ui.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare function printBanner(): void;
2
+ export declare function printTable(rows: any[], columns: {
3
+ key: string;
4
+ label: string;
5
+ width?: number;
6
+ }[]): void;
7
+ export declare function printObject(obj: any, title?: string): void;
8
+ export declare function error(msg: string): void;
9
+ export declare function success(msg: string): void;
package/dist/ui.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.printBanner = printBanner;
7
+ exports.printTable = printTable;
8
+ exports.printObject = printObject;
9
+ exports.error = error;
10
+ exports.success = success;
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const figlet_1 = __importDefault(require("figlet"));
13
+ function printBanner() {
14
+ const banner = figlet_1.default.textSync('incwo CLI', {
15
+ font: 'ANSI Shadow',
16
+ horizontalLayout: 'default',
17
+ });
18
+ console.log(chalk_1.default.cyan(banner));
19
+ console.log(chalk_1.default.dim(' Your CRM/ERP · incwo.com\n'));
20
+ }
21
+ function printTable(rows, columns) {
22
+ if (!rows || rows.length === 0) {
23
+ console.log(chalk_1.default.yellow(' No results.'));
24
+ return;
25
+ }
26
+ const widths = columns.map(col => {
27
+ const max = Math.max(col.label.length, ...rows.map(r => String(r[col.key] ?? '').length));
28
+ return col.width ?? Math.min(max, 40);
29
+ });
30
+ const header = columns.map((col, i) => col.label.padEnd(widths[i])).join(' ');
31
+ const separator = widths.map(w => '─'.repeat(w)).join(' ');
32
+ console.log(chalk_1.default.bold(' ' + header));
33
+ console.log(chalk_1.default.dim(' ' + separator));
34
+ for (const row of rows) {
35
+ const line = columns.map((col, i) => {
36
+ const val = String(row[col.key] ?? '');
37
+ return val.length > widths[i] ? val.substring(0, widths[i] - 1) + '…' : val.padEnd(widths[i]);
38
+ }).join(' ');
39
+ console.log(' ' + line);
40
+ }
41
+ console.log(chalk_1.default.dim(`\n ${rows.length} result(s)`));
42
+ }
43
+ function printObject(obj, title) {
44
+ if (title)
45
+ console.log(chalk_1.default.bold(`\n ${title}\n`));
46
+ for (const [key, value] of Object.entries(obj)) {
47
+ if (value !== null && value !== undefined && value !== '') {
48
+ console.log(` ${chalk_1.default.dim(key.padEnd(28))} ${value}`);
49
+ }
50
+ }
51
+ console.log();
52
+ }
53
+ function error(msg) {
54
+ console.error(chalk_1.default.red(`\n ✗ ${msg}\n`));
55
+ }
56
+ function success(msg) {
57
+ console.log(chalk_1.default.green(`\n ✓ ${msg}\n`));
58
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "incwo-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for incwo CRM/ERP",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "incwo": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "ts-node src/index.ts",
12
+ "start": "node dist/index.js",
13
+ "prepare": "husky"
14
+ },
15
+ "dependencies": {
16
+ "axios": "^1.6.0",
17
+ "chalk": "^4.1.2",
18
+ "commander": "^11.1.0",
19
+ "figlet": "^1.7.0",
20
+ "inquirer": "^8.2.6",
21
+ "ora": "^5.4.1",
22
+ "xml2js": "^0.6.2"
23
+ },
24
+ "devDependencies": {
25
+ "@types/figlet": "^1.5.8",
26
+ "@types/inquirer": "^8.2.10",
27
+ "@types/node": "^20.10.0",
28
+ "@types/xml2js": "^0.4.14",
29
+ "husky": "^9.1.7",
30
+ "ts-node": "^10.9.2",
31
+ "typescript": "^5.3.2"
32
+ }
33
+ }