@klevar/portal-cli 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/_exemptions.d.ts +6 -0
- package/dist/commands/_exemptions.js +7 -0
- package/dist/commands/_exemptions.js.map +1 -1
- package/dist/commands/index.d.ts +137 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/operator.d.ts +137 -0
- package/dist/commands/operator.js +138 -0
- package/dist/commands/operator.js.map +1 -0
- package/dist/lib/legacy-runner.js +206 -9
- package/package.json +1 -1
|
@@ -28,6 +28,12 @@ export declare const CLI_EXEMPTIONS: readonly [{
|
|
|
28
28
|
readonly reason: "Inbound webhook consumer called by Klevar Docs, not by operators or clients.";
|
|
29
29
|
readonly owner: "Klevar Docs";
|
|
30
30
|
readonly trackedAs: "Phase 17 inbound-webhook exemption";
|
|
31
|
+
}, {
|
|
32
|
+
readonly method: "GET";
|
|
33
|
+
readonly path: "/api/portal/projects/:id/timeline";
|
|
34
|
+
readonly reason: "Client-facing timeline used by the portal project UI; admin/operator timeline CLI already covers recall workflows.";
|
|
35
|
+
readonly owner: "Klevar Portal";
|
|
36
|
+
readonly trackedAs: "Phase 17 client timeline portal-ui exemption";
|
|
31
37
|
}, {
|
|
32
38
|
readonly method: "GET";
|
|
33
39
|
readonly path: "/api/portal/projects/:projectId/recurring-checkpoints";
|
|
@@ -34,6 +34,13 @@ export const CLI_EXEMPTIONS = [
|
|
|
34
34
|
owner: 'Klevar Docs',
|
|
35
35
|
trackedAs: 'Phase 17 inbound-webhook exemption',
|
|
36
36
|
},
|
|
37
|
+
{
|
|
38
|
+
method: 'GET',
|
|
39
|
+
path: '/api/portal/projects/:id/timeline',
|
|
40
|
+
reason: 'Client-facing timeline used by the portal project UI; admin/operator timeline CLI already covers recall workflows.',
|
|
41
|
+
owner: 'Klevar Portal',
|
|
42
|
+
trackedAs: 'Phase 17 client timeline portal-ui exemption',
|
|
43
|
+
},
|
|
37
44
|
{
|
|
38
45
|
method: 'GET',
|
|
39
46
|
path: '/api/portal/projects/:projectId/recurring-checkpoints',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_exemptions.js","sourceRoot":"","sources":["../../commands/_exemptions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,0GAA0G;QAClH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uBAAuB;QAC7B,MAAM,EAAE,yGAAyG;QACjH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,qCAAqC;KACjD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,qCAAqC;QAC3C,MAAM,EAAE,8EAA8E;QACtF,KAAK,EAAE,aAAa;QACpB,SAAS,EAAE,oCAAoC;KAChD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,qFAAqF;QAC7F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,uFAAuF;QAC/F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,wDAAwD;QAChE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,uDAAuD;QAC/D,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,mDAAmD;QACzD,MAAM,EAAE,yDAAyD;QACjE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;CACO,CAAC"}
|
|
1
|
+
{"version":3,"file":"_exemptions.js","sourceRoot":"","sources":["../../commands/_exemptions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,0GAA0G;QAClH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uBAAuB;QAC7B,MAAM,EAAE,yGAAyG;QACjH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,qCAAqC;KACjD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,qCAAqC;QAC3C,MAAM,EAAE,8EAA8E;QACtF,KAAK,EAAE,aAAa;QACpB,SAAS,EAAE,oCAAoC;KAChD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,mCAAmC;QACzC,MAAM,EAAE,oHAAoH;QAC5H,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,8CAA8C;KAC1D;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,qFAAqF;QAC7F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,uFAAuF;QAC/F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,wDAAwD;QAChE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,uDAAuD;QAC/D,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,mDAAmD;QACzD,MAAM,EAAE,yDAAyD;QACjE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;CACO,CAAC"}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -522,6 +522,143 @@ export declare const COMMAND_GROUPS: {
|
|
|
522
522
|
description: string;
|
|
523
523
|
};
|
|
524
524
|
};
|
|
525
|
+
operator: {
|
|
526
|
+
inbox: {
|
|
527
|
+
method: "GET";
|
|
528
|
+
path: string;
|
|
529
|
+
auth: "apiKey";
|
|
530
|
+
description: string;
|
|
531
|
+
queryParams: string[];
|
|
532
|
+
};
|
|
533
|
+
'inbox.mark-read': {
|
|
534
|
+
method: "POST";
|
|
535
|
+
path: string;
|
|
536
|
+
auth: "apiKey";
|
|
537
|
+
description: string;
|
|
538
|
+
};
|
|
539
|
+
'inbox.mark-client-read': {
|
|
540
|
+
method: "POST";
|
|
541
|
+
path: string;
|
|
542
|
+
auth: "apiKey";
|
|
543
|
+
description: string;
|
|
544
|
+
};
|
|
545
|
+
'inbox.mark-project-read': {
|
|
546
|
+
method: "POST";
|
|
547
|
+
path: string;
|
|
548
|
+
auth: "apiKey";
|
|
549
|
+
description: string;
|
|
550
|
+
};
|
|
551
|
+
'inbox.mark-all-read': {
|
|
552
|
+
method: "POST";
|
|
553
|
+
path: string;
|
|
554
|
+
auth: "apiKey";
|
|
555
|
+
description: string;
|
|
556
|
+
};
|
|
557
|
+
'reports.monthly': {
|
|
558
|
+
method: "GET";
|
|
559
|
+
path: string;
|
|
560
|
+
auth: "apiKey";
|
|
561
|
+
description: string;
|
|
562
|
+
queryParams: string[];
|
|
563
|
+
};
|
|
564
|
+
'client.timeline': {
|
|
565
|
+
method: "GET";
|
|
566
|
+
path: string;
|
|
567
|
+
auth: "apiKey";
|
|
568
|
+
description: string;
|
|
569
|
+
queryParams: string[];
|
|
570
|
+
};
|
|
571
|
+
'project.timeline': {
|
|
572
|
+
method: "GET";
|
|
573
|
+
path: string;
|
|
574
|
+
auth: "apiKey";
|
|
575
|
+
description: string;
|
|
576
|
+
queryParams: string[];
|
|
577
|
+
};
|
|
578
|
+
'ops-health': {
|
|
579
|
+
method: "GET";
|
|
580
|
+
path: string;
|
|
581
|
+
auth: "apiKey";
|
|
582
|
+
description: string;
|
|
583
|
+
};
|
|
584
|
+
'smoke.portal': {
|
|
585
|
+
method: "GET";
|
|
586
|
+
path: string;
|
|
587
|
+
auth: "apiKey";
|
|
588
|
+
description: string;
|
|
589
|
+
};
|
|
590
|
+
'smoke.docs': {
|
|
591
|
+
method: "GET";
|
|
592
|
+
path: string;
|
|
593
|
+
auth: "apiKey";
|
|
594
|
+
description: string;
|
|
595
|
+
};
|
|
596
|
+
'smoke.capacity': {
|
|
597
|
+
method: "GET";
|
|
598
|
+
path: string;
|
|
599
|
+
auth: "apiKey";
|
|
600
|
+
description: string;
|
|
601
|
+
};
|
|
602
|
+
'smoke.recurring': {
|
|
603
|
+
method: "GET";
|
|
604
|
+
path: string;
|
|
605
|
+
auth: "apiKey";
|
|
606
|
+
description: string;
|
|
607
|
+
};
|
|
608
|
+
'smoke.notifications': {
|
|
609
|
+
method: "GET";
|
|
610
|
+
path: string;
|
|
611
|
+
auth: "apiKey";
|
|
612
|
+
description: string;
|
|
613
|
+
};
|
|
614
|
+
'clients.notifications.get': {
|
|
615
|
+
method: "GET";
|
|
616
|
+
path: string;
|
|
617
|
+
auth: "apiKey";
|
|
618
|
+
description: string;
|
|
619
|
+
};
|
|
620
|
+
'clients.notifications.update': {
|
|
621
|
+
method: "PATCH";
|
|
622
|
+
path: string;
|
|
623
|
+
auth: "apiKey";
|
|
624
|
+
description: string;
|
|
625
|
+
body: string[];
|
|
626
|
+
};
|
|
627
|
+
'projects.notifications.get': {
|
|
628
|
+
method: "GET";
|
|
629
|
+
path: string;
|
|
630
|
+
auth: "apiKey";
|
|
631
|
+
description: string;
|
|
632
|
+
};
|
|
633
|
+
'projects.notifications.update': {
|
|
634
|
+
method: "PATCH";
|
|
635
|
+
path: string;
|
|
636
|
+
auth: "apiKey";
|
|
637
|
+
description: string;
|
|
638
|
+
body: string[];
|
|
639
|
+
};
|
|
640
|
+
'notifications.preview': {
|
|
641
|
+
method: "GET";
|
|
642
|
+
path: string;
|
|
643
|
+
auth: "apiKey";
|
|
644
|
+
description: string;
|
|
645
|
+
queryParams: string[];
|
|
646
|
+
};
|
|
647
|
+
'audit.list': {
|
|
648
|
+
method: "GET";
|
|
649
|
+
path: string;
|
|
650
|
+
auth: "apiKey";
|
|
651
|
+
description: string;
|
|
652
|
+
queryParams: string[];
|
|
653
|
+
};
|
|
654
|
+
'audit.target': {
|
|
655
|
+
method: "GET";
|
|
656
|
+
path: string;
|
|
657
|
+
auth: "apiKey";
|
|
658
|
+
description: string;
|
|
659
|
+
queryParams: string[];
|
|
660
|
+
};
|
|
661
|
+
};
|
|
525
662
|
notes: {
|
|
526
663
|
'notes.list': {
|
|
527
664
|
method: "GET";
|
package/dist/commands/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { docsCommands } from './docs.js';
|
|
|
3
3
|
import { capacityCommands } from './capacity.js';
|
|
4
4
|
import { metricCommands } from './metrics.js';
|
|
5
5
|
import { onboardingCommands } from './onboarding.js';
|
|
6
|
+
import { operatorCommands } from './operator.js';
|
|
6
7
|
import { noteCommands } from './notes.js';
|
|
7
8
|
import { portalCommands } from './portal.js';
|
|
8
9
|
import { projectCommands } from './projects.js';
|
|
@@ -20,6 +21,7 @@ export const COMMAND_GROUPS = {
|
|
|
20
21
|
usage: usageCommands,
|
|
21
22
|
updates: updateCommands,
|
|
22
23
|
onboarding: onboardingCommands,
|
|
24
|
+
operator: operatorCommands,
|
|
23
25
|
notes: noteCommands,
|
|
24
26
|
recurring: recurringCommands,
|
|
25
27
|
metrics: metricCommands,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAK9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,cAAc;IACtB,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,eAAe;IACzB,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,gBAAgB;IAC1B,KAAK,EAAE,aAAa;IACpB,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,kBAAkB;IAC9B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,cAAc;IACvB,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,cAAc;CACgB,CAAC;AAEzC,MAAM,CAAC,MAAM,QAAQ,GAA+B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAK9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,cAAc;IACtB,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,eAAe;IACzB,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,gBAAgB;IAC1B,KAAK,EAAE,aAAa;IACpB,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,kBAAkB;IAC9B,QAAQ,EAAE,gBAAgB;IAC1B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,cAAc;IACvB,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,cAAc;CACgB,CAAC;AAEzC,MAAM,CAAC,MAAM,QAAQ,GAA+B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export declare const operatorCommands: {
|
|
2
|
+
inbox: {
|
|
3
|
+
method: "GET";
|
|
4
|
+
path: string;
|
|
5
|
+
auth: "apiKey";
|
|
6
|
+
description: string;
|
|
7
|
+
queryParams: string[];
|
|
8
|
+
};
|
|
9
|
+
'inbox.mark-read': {
|
|
10
|
+
method: "POST";
|
|
11
|
+
path: string;
|
|
12
|
+
auth: "apiKey";
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
'inbox.mark-client-read': {
|
|
16
|
+
method: "POST";
|
|
17
|
+
path: string;
|
|
18
|
+
auth: "apiKey";
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
'inbox.mark-project-read': {
|
|
22
|
+
method: "POST";
|
|
23
|
+
path: string;
|
|
24
|
+
auth: "apiKey";
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
'inbox.mark-all-read': {
|
|
28
|
+
method: "POST";
|
|
29
|
+
path: string;
|
|
30
|
+
auth: "apiKey";
|
|
31
|
+
description: string;
|
|
32
|
+
};
|
|
33
|
+
'reports.monthly': {
|
|
34
|
+
method: "GET";
|
|
35
|
+
path: string;
|
|
36
|
+
auth: "apiKey";
|
|
37
|
+
description: string;
|
|
38
|
+
queryParams: string[];
|
|
39
|
+
};
|
|
40
|
+
'client.timeline': {
|
|
41
|
+
method: "GET";
|
|
42
|
+
path: string;
|
|
43
|
+
auth: "apiKey";
|
|
44
|
+
description: string;
|
|
45
|
+
queryParams: string[];
|
|
46
|
+
};
|
|
47
|
+
'project.timeline': {
|
|
48
|
+
method: "GET";
|
|
49
|
+
path: string;
|
|
50
|
+
auth: "apiKey";
|
|
51
|
+
description: string;
|
|
52
|
+
queryParams: string[];
|
|
53
|
+
};
|
|
54
|
+
'ops-health': {
|
|
55
|
+
method: "GET";
|
|
56
|
+
path: string;
|
|
57
|
+
auth: "apiKey";
|
|
58
|
+
description: string;
|
|
59
|
+
};
|
|
60
|
+
'smoke.portal': {
|
|
61
|
+
method: "GET";
|
|
62
|
+
path: string;
|
|
63
|
+
auth: "apiKey";
|
|
64
|
+
description: string;
|
|
65
|
+
};
|
|
66
|
+
'smoke.docs': {
|
|
67
|
+
method: "GET";
|
|
68
|
+
path: string;
|
|
69
|
+
auth: "apiKey";
|
|
70
|
+
description: string;
|
|
71
|
+
};
|
|
72
|
+
'smoke.capacity': {
|
|
73
|
+
method: "GET";
|
|
74
|
+
path: string;
|
|
75
|
+
auth: "apiKey";
|
|
76
|
+
description: string;
|
|
77
|
+
};
|
|
78
|
+
'smoke.recurring': {
|
|
79
|
+
method: "GET";
|
|
80
|
+
path: string;
|
|
81
|
+
auth: "apiKey";
|
|
82
|
+
description: string;
|
|
83
|
+
};
|
|
84
|
+
'smoke.notifications': {
|
|
85
|
+
method: "GET";
|
|
86
|
+
path: string;
|
|
87
|
+
auth: "apiKey";
|
|
88
|
+
description: string;
|
|
89
|
+
};
|
|
90
|
+
'clients.notifications.get': {
|
|
91
|
+
method: "GET";
|
|
92
|
+
path: string;
|
|
93
|
+
auth: "apiKey";
|
|
94
|
+
description: string;
|
|
95
|
+
};
|
|
96
|
+
'clients.notifications.update': {
|
|
97
|
+
method: "PATCH";
|
|
98
|
+
path: string;
|
|
99
|
+
auth: "apiKey";
|
|
100
|
+
description: string;
|
|
101
|
+
body: string[];
|
|
102
|
+
};
|
|
103
|
+
'projects.notifications.get': {
|
|
104
|
+
method: "GET";
|
|
105
|
+
path: string;
|
|
106
|
+
auth: "apiKey";
|
|
107
|
+
description: string;
|
|
108
|
+
};
|
|
109
|
+
'projects.notifications.update': {
|
|
110
|
+
method: "PATCH";
|
|
111
|
+
path: string;
|
|
112
|
+
auth: "apiKey";
|
|
113
|
+
description: string;
|
|
114
|
+
body: string[];
|
|
115
|
+
};
|
|
116
|
+
'notifications.preview': {
|
|
117
|
+
method: "GET";
|
|
118
|
+
path: string;
|
|
119
|
+
auth: "apiKey";
|
|
120
|
+
description: string;
|
|
121
|
+
queryParams: string[];
|
|
122
|
+
};
|
|
123
|
+
'audit.list': {
|
|
124
|
+
method: "GET";
|
|
125
|
+
path: string;
|
|
126
|
+
auth: "apiKey";
|
|
127
|
+
description: string;
|
|
128
|
+
queryParams: string[];
|
|
129
|
+
};
|
|
130
|
+
'audit.target': {
|
|
131
|
+
method: "GET";
|
|
132
|
+
path: string;
|
|
133
|
+
auth: "apiKey";
|
|
134
|
+
description: string;
|
|
135
|
+
queryParams: string[];
|
|
136
|
+
};
|
|
137
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export const operatorCommands = {
|
|
2
|
+
inbox: {
|
|
3
|
+
method: 'GET',
|
|
4
|
+
path: '/api/admin/operator-inbox',
|
|
5
|
+
auth: 'apiKey',
|
|
6
|
+
description: 'Review operator inbox',
|
|
7
|
+
queryParams: ['clientId|client', 'projectId|project', 'since', 'unreadOnly|unread', 'limit'],
|
|
8
|
+
},
|
|
9
|
+
'inbox.mark-read': {
|
|
10
|
+
method: 'POST',
|
|
11
|
+
path: '/api/admin/operator-inbox/read/:itemId',
|
|
12
|
+
auth: 'apiKey',
|
|
13
|
+
description: 'Mark one inbox item read',
|
|
14
|
+
},
|
|
15
|
+
'inbox.mark-client-read': {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
path: '/api/admin/operator-inbox/read-client/:clientId',
|
|
18
|
+
auth: 'apiKey',
|
|
19
|
+
description: 'Mark a client inbox section read',
|
|
20
|
+
},
|
|
21
|
+
'inbox.mark-project-read': {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
path: '/api/admin/operator-inbox/read-project/:projectId',
|
|
24
|
+
auth: 'apiKey',
|
|
25
|
+
description: 'Mark a project inbox section read',
|
|
26
|
+
},
|
|
27
|
+
'inbox.mark-all-read': {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
path: '/api/admin/operator-inbox/read-all',
|
|
30
|
+
auth: 'apiKey',
|
|
31
|
+
description: 'Mark all current inbox items read',
|
|
32
|
+
},
|
|
33
|
+
'reports.monthly': {
|
|
34
|
+
method: 'GET',
|
|
35
|
+
path: '/api/admin/clients/:clientId/reports/monthly',
|
|
36
|
+
auth: 'apiKey',
|
|
37
|
+
description: 'Generate monthly client report',
|
|
38
|
+
queryParams: ['period'],
|
|
39
|
+
},
|
|
40
|
+
'client.timeline': {
|
|
41
|
+
method: 'GET',
|
|
42
|
+
path: '/api/admin/clients/:clientId/timeline',
|
|
43
|
+
auth: 'apiKey',
|
|
44
|
+
description: 'Show client timeline',
|
|
45
|
+
queryParams: ['projectId|project', 'type', 'since', 'until', 'limit'],
|
|
46
|
+
},
|
|
47
|
+
'project.timeline': {
|
|
48
|
+
method: 'GET',
|
|
49
|
+
path: '/api/admin/projects/:projectId/timeline',
|
|
50
|
+
auth: 'apiKey',
|
|
51
|
+
description: 'Show project timeline',
|
|
52
|
+
queryParams: ['type', 'since', 'until', 'limit'],
|
|
53
|
+
},
|
|
54
|
+
'ops-health': {
|
|
55
|
+
method: 'GET',
|
|
56
|
+
path: '/api/admin/ops-health',
|
|
57
|
+
auth: 'apiKey',
|
|
58
|
+
description: 'Show operational health summary',
|
|
59
|
+
},
|
|
60
|
+
'smoke.portal': {
|
|
61
|
+
method: 'GET',
|
|
62
|
+
path: '/api/admin/clients/:id',
|
|
63
|
+
auth: 'apiKey',
|
|
64
|
+
description: 'Read-only portal smoke check',
|
|
65
|
+
},
|
|
66
|
+
'smoke.docs': {
|
|
67
|
+
method: 'GET',
|
|
68
|
+
path: '/api/admin/clients/:id/docs/documents',
|
|
69
|
+
auth: 'apiKey',
|
|
70
|
+
description: 'Read-only Docs smoke check',
|
|
71
|
+
},
|
|
72
|
+
'smoke.capacity': {
|
|
73
|
+
method: 'GET',
|
|
74
|
+
path: '/api/admin/projects/:projectId/capacity-summary',
|
|
75
|
+
auth: 'apiKey',
|
|
76
|
+
description: 'Read-only capacity smoke check',
|
|
77
|
+
},
|
|
78
|
+
'smoke.recurring': {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
path: '/api/admin/projects/:projectId/recurring-checkpoints',
|
|
81
|
+
auth: 'apiKey',
|
|
82
|
+
description: 'Read-only recurring smoke check',
|
|
83
|
+
},
|
|
84
|
+
'smoke.notifications': {
|
|
85
|
+
method: 'GET',
|
|
86
|
+
path: '/api/admin/smoke/notifications/:clientId',
|
|
87
|
+
auth: 'apiKey',
|
|
88
|
+
description: 'Read-only notification smoke check',
|
|
89
|
+
},
|
|
90
|
+
'clients.notifications.get': {
|
|
91
|
+
method: 'GET',
|
|
92
|
+
path: '/api/admin/clients/:id/notification-preferences',
|
|
93
|
+
auth: 'apiKey',
|
|
94
|
+
description: 'Show client notification preferences',
|
|
95
|
+
},
|
|
96
|
+
'clients.notifications.update': {
|
|
97
|
+
method: 'PATCH',
|
|
98
|
+
path: '/api/admin/clients/:id/notification-preferences',
|
|
99
|
+
auth: 'apiKey',
|
|
100
|
+
description: 'Update client notification preferences',
|
|
101
|
+
body: ['mode', 'digestFrequency'],
|
|
102
|
+
},
|
|
103
|
+
'projects.notifications.get': {
|
|
104
|
+
method: 'GET',
|
|
105
|
+
path: '/api/admin/projects/:id/notification-preferences',
|
|
106
|
+
auth: 'apiKey',
|
|
107
|
+
description: 'Show project notification preferences',
|
|
108
|
+
},
|
|
109
|
+
'projects.notifications.update': {
|
|
110
|
+
method: 'PATCH',
|
|
111
|
+
path: '/api/admin/projects/:id/notification-preferences',
|
|
112
|
+
auth: 'apiKey',
|
|
113
|
+
description: 'Update project notification preferences',
|
|
114
|
+
body: ['mode', 'digestFrequency'],
|
|
115
|
+
},
|
|
116
|
+
'notifications.preview': {
|
|
117
|
+
method: 'GET',
|
|
118
|
+
path: '/api/admin/notifications/preview/:eventType',
|
|
119
|
+
auth: 'apiKey',
|
|
120
|
+
description: 'Preview notification rendering without sending',
|
|
121
|
+
queryParams: ['clientId|client', 'projectId|project'],
|
|
122
|
+
},
|
|
123
|
+
'audit.list': {
|
|
124
|
+
method: 'GET',
|
|
125
|
+
path: '/api/admin/audit-events',
|
|
126
|
+
auth: 'apiKey',
|
|
127
|
+
description: 'List operational audit events',
|
|
128
|
+
queryParams: ['clientId|client', 'projectId|project', 'actorId|actor', 'action', 'targetType', 'targetId', 'since', 'until', 'limit'],
|
|
129
|
+
},
|
|
130
|
+
'audit.target': {
|
|
131
|
+
method: 'GET',
|
|
132
|
+
path: '/api/admin/audit-events',
|
|
133
|
+
auth: 'apiKey',
|
|
134
|
+
description: 'List audit events for one target',
|
|
135
|
+
queryParams: ['targetType', 'targetId', 'limit'],
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=operator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator.js","sourceRoot":"","sources":["../../commands/operator.ts"],"names":[],"mappings":"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"}
|
|
@@ -299,6 +299,42 @@ function interpolatePath(template, id) {
|
|
|
299
299
|
return template.replace(':id', id);
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
function isUuid(value) {
|
|
303
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function looksLikeOpaqueId(value) {
|
|
307
|
+
return isUuid(value) || /^[a-z]+-\d+$/i.test(value);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function pathParamEntity(commandKey, paramName) {
|
|
311
|
+
if (paramName.toLowerCase().includes('client')) return 'client';
|
|
312
|
+
if (paramName.toLowerCase().includes('project')) return 'project';
|
|
313
|
+
if (paramName === 'id' && commandKey.startsWith('clients.')) return 'client';
|
|
314
|
+
if (paramName === 'id' && commandKey.startsWith('projects.')) return 'project';
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async function resolveNameParam(commandKey, paramName, value, flags) {
|
|
319
|
+
if (!value || looksLikeOpaqueId(value)) return value;
|
|
320
|
+
const entity = pathParamEntity(commandKey, paramName);
|
|
321
|
+
if (!entity) return value;
|
|
322
|
+
const params = new URLSearchParams({ q: value, type: entity, limit: '10' });
|
|
323
|
+
if (entity === 'project' && flags.client) params.set('client', flags.client);
|
|
324
|
+
if (entity === 'project' && flags.clientId) params.set('clientId', flags.clientId);
|
|
325
|
+
const data = await api('GET', `/api/admin/search?${params.toString()}`);
|
|
326
|
+
const rows = entity === 'client' ? (data.clients || []) : (data.projects || []);
|
|
327
|
+
const exact = rows.filter((row) => (row.name || '').toLowerCase() === value.toLowerCase());
|
|
328
|
+
const candidates = exact.length > 0 ? exact : rows;
|
|
329
|
+
if (candidates.length === 1) return candidates[0].id;
|
|
330
|
+
if (candidates.length === 0) console.error(`No ${entity} found for "${value}".`);
|
|
331
|
+
else {
|
|
332
|
+
console.error(`Ambiguous ${entity} name "${value}". Use an ID or narrow the search.`);
|
|
333
|
+
for (const row of candidates.slice(0, 5)) console.error(` ${row.name} [${row.id}]`);
|
|
334
|
+
}
|
|
335
|
+
exitGracefully(2);
|
|
336
|
+
}
|
|
337
|
+
|
|
302
338
|
const HELP_ENUMS = {
|
|
303
339
|
priority: 'low|normal|high|urgent',
|
|
304
340
|
submittedBy: 'client|admin|va|system',
|
|
@@ -320,10 +356,11 @@ const HELP_ENUMS = {
|
|
|
320
356
|
cadence: 'weekly|biweekly|monthly|quarterly|custom_days',
|
|
321
357
|
cadenceType: 'weekly|biweekly|monthly|quarterly|custom_days',
|
|
322
358
|
outputType: 'task|project_update_draft|project_update|email_reminder',
|
|
323
|
-
notificationMode: 'silent|admin_only|client_on_acceptance|client_each_occurrence|client_digest_only',
|
|
324
359
|
owner: 'admin|client|shared',
|
|
325
360
|
requiresClientAcceptance: 'true|false',
|
|
326
361
|
requiresAdminAcceptance: 'true|false',
|
|
362
|
+
mode: 'muted|portal_only|admin_only|material_updates|digest|all',
|
|
363
|
+
digestFrequency: 'daily|weekly|monthly',
|
|
327
364
|
};
|
|
328
365
|
|
|
329
366
|
function helpFlag(commandKey, field) {
|
|
@@ -339,6 +376,10 @@ function helpFlag(commandKey, field) {
|
|
|
339
376
|
else if (commandKey.startsWith('capacity.')) hint = 'active|paused|ended';
|
|
340
377
|
else if (commandKey.startsWith('tasks.')) hint = 'open|in_progress|done|blocked';
|
|
341
378
|
}
|
|
379
|
+
if (field === 'notificationMode') {
|
|
380
|
+
if (commandKey.startsWith('recurring.')) hint = 'silent|admin_only|client_on_acceptance|client_each_occurrence|client_digest_only';
|
|
381
|
+
else if (commandKey.startsWith('tasks.')) hint = 'silent|ack_only|material_updates|all';
|
|
382
|
+
}
|
|
342
383
|
return hint ? `--${field} ${hint}` : `--${field}`;
|
|
343
384
|
}
|
|
344
385
|
|
|
@@ -353,6 +394,11 @@ function helpQueryFlag(field) {
|
|
|
353
394
|
// ── Output Formatting ───────────────────────────────────────────
|
|
354
395
|
|
|
355
396
|
function formatOutput(data, commandKey) {
|
|
397
|
+
if (commandKey === 'ops-health' && OUTPUT_JSON) {
|
|
398
|
+
console.log(COMPACT_JSON ? JSON.stringify(data) : JSON.stringify(data, null, 2));
|
|
399
|
+
if (data.status === 'critical') exitGracefully(1);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
356
402
|
if (OUTPUT_JSON) {
|
|
357
403
|
console.log(COMPACT_JSON ? JSON.stringify(data) : JSON.stringify(data, null, 2));
|
|
358
404
|
return;
|
|
@@ -419,6 +465,111 @@ function formatOutput(data, commandKey) {
|
|
|
419
465
|
return;
|
|
420
466
|
}
|
|
421
467
|
|
|
468
|
+
if (commandKey === 'inbox') {
|
|
469
|
+
const sections = data.sections || {};
|
|
470
|
+
console.log('\nOperator Inbox');
|
|
471
|
+
console.log('-'.repeat(80));
|
|
472
|
+
for (const [key, section] of Object.entries(sections)) {
|
|
473
|
+
const items = section.items || [];
|
|
474
|
+
if (items.length === 0) continue;
|
|
475
|
+
console.log(`\n${key} (${items.length})`);
|
|
476
|
+
for (const item of items) {
|
|
477
|
+
const unread = item.unread ? '*' : ' ';
|
|
478
|
+
const scope = [item.clientName, item.projectName].filter(Boolean).join(' / ');
|
|
479
|
+
console.log(` ${unread} ${item.summary} ${scope ? `- ${scope}` : ''} [${item.id}]`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (commandKey === 'reports.monthly') {
|
|
486
|
+
const report = data.report;
|
|
487
|
+
if (!report) { console.log(JSON.stringify(data, null, 2)); return; }
|
|
488
|
+
if (COMPACT_JSON) {
|
|
489
|
+
console.log(`${report.client.name}: ${report.period} - ${report.completedWork.length} done, ${report.openWork.length} open`);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
console.log(`\nMonthly Report: ${report.client.name} (${report.period})`);
|
|
493
|
+
console.log('-'.repeat(80));
|
|
494
|
+
console.log(`Completed work: ${report.completedWork.length}`);
|
|
495
|
+
for (const item of report.completedWork) console.log(` - ${item.title}`);
|
|
496
|
+
console.log(`Open work: ${report.openWork.length}`);
|
|
497
|
+
for (const item of report.openWork) console.log(` - ${item.title} [${item.status}]`);
|
|
498
|
+
console.log(`Updates: ${report.updates.length}`);
|
|
499
|
+
console.log(`Invoices: ${report.invoices.length}`);
|
|
500
|
+
console.log(`Capacity items: ${report.capacity.length}`);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (commandKey === 'client.timeline' || commandKey === 'project.timeline') {
|
|
505
|
+
const items = data.data || [];
|
|
506
|
+
if (items.length === 0) { console.log('No timeline events found.'); return; }
|
|
507
|
+
console.log(`\nTimeline (${items.length})`);
|
|
508
|
+
console.log('-'.repeat(80));
|
|
509
|
+
for (const item of items) {
|
|
510
|
+
const scope = [item.clientName, item.projectName].filter(Boolean).join(' / ');
|
|
511
|
+
console.log(` ${item.type}: ${item.summary}${scope ? ` - ${scope}` : ''} [${item.sourceId}]`);
|
|
512
|
+
}
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (commandKey === 'ops-health') {
|
|
517
|
+
console.log(`Operational health: ${data.status}`);
|
|
518
|
+
for (const [key, value] of Object.entries(data.failures || {})) {
|
|
519
|
+
console.log(` ${key}: ${value}`);
|
|
520
|
+
}
|
|
521
|
+
if (data.status === 'critical') exitGracefully(1);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (commandKey === 'smoke.notifications') {
|
|
526
|
+
const smoke = data.smoke || {};
|
|
527
|
+
console.log(`Notification smoke: ${smoke.client?.name || 'client'}`);
|
|
528
|
+
console.log(` Read-only dry run: ${smoke.dryRun === false ? 'false' : 'true'}`);
|
|
529
|
+
console.log(` notificationsEnabled: ${smoke.client?.notificationsEnabled}`);
|
|
530
|
+
console.log(` preference: ${smoke.preference?.mode || 'n/a'}`);
|
|
531
|
+
console.log(` failed deliveries: ${smoke.failedCount ?? 0}`);
|
|
532
|
+
console.log(' Would send: none');
|
|
533
|
+
console.log(' Would create: none');
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (
|
|
538
|
+
commandKey === 'clients.notifications.get' ||
|
|
539
|
+
commandKey === 'clients.notifications.update' ||
|
|
540
|
+
commandKey === 'projects.notifications.get' ||
|
|
541
|
+
commandKey === 'projects.notifications.update'
|
|
542
|
+
) {
|
|
543
|
+
const preference = data.preference || {};
|
|
544
|
+
console.log(`Notification preference: ${preference.mode || 'n/a'}`);
|
|
545
|
+
if (preference.digestFrequency) console.log(` Digest: ${preference.digestFrequency}`);
|
|
546
|
+
if (preference.inheritedFromClient) console.log(' Inherited from client preference.');
|
|
547
|
+
if (preference.inheritedFromNotificationsEnabled) console.log(' Inherited from notificationsEnabled.');
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (commandKey === 'notifications.preview') {
|
|
552
|
+
const preview = data.preview || {};
|
|
553
|
+
console.log(`Notification preview: ${preview.subject || preview.eventType}`);
|
|
554
|
+
console.log(` Audience: ${(preview.audience || []).join(', ') || 'none'}`);
|
|
555
|
+
console.log(` Mode: ${preview.mode || 'n/a'}`);
|
|
556
|
+
console.log(` Thread: ${preview.threadKey || 'n/a'}`);
|
|
557
|
+
console.log('');
|
|
558
|
+
console.log(preview.body || '');
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if (commandKey === 'audit.list' || commandKey === 'audit.target') {
|
|
563
|
+
const items = data.data || [];
|
|
564
|
+
if (items.length === 0) { console.log('No audit events found.'); return; }
|
|
565
|
+
console.log(`\nAudit Events (${items.length})`);
|
|
566
|
+
console.log('-'.repeat(80));
|
|
567
|
+
for (const item of items) {
|
|
568
|
+
console.log(` ${item.action}: ${item.targetType}/${item.targetId} [${item.id}]`);
|
|
569
|
+
}
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
|
|
422
573
|
if (commandKey === 'projects.get') {
|
|
423
574
|
const p = data.project;
|
|
424
575
|
console.log(`\n${p.name} [${p.status}]`);
|
|
@@ -775,6 +926,11 @@ if (!resource || resource === 'help' || resource === '--help') {
|
|
|
775
926
|
}
|
|
776
927
|
console.log(`\nConfig: PORTAL_API_URL, PORTAL_API_KEY, PORTAL_TOKEN (or ~/.klevar/portal.env)`);
|
|
777
928
|
console.log(`Target: ${BASE_URL}`);
|
|
929
|
+
console.log('\nExamples:');
|
|
930
|
+
console.log(' klevar-portal inbox --unread --compact');
|
|
931
|
+
console.log(' klevar-portal client timeline "Acme Ltd" --type task');
|
|
932
|
+
console.log(' klevar-portal notifications preview project.status_changed --client "Acme Ltd" --project "Retainer"');
|
|
933
|
+
console.log(' klevar-portal audit target task <taskId>');
|
|
778
934
|
exitGracefully(0);
|
|
779
935
|
}
|
|
780
936
|
|
|
@@ -824,19 +980,25 @@ if (supportsCommentContentInput(commandKey)) {
|
|
|
824
980
|
}
|
|
825
981
|
}
|
|
826
982
|
|
|
983
|
+
if (commandKey === 'audit.target' && positional.length >= 2) {
|
|
984
|
+
flags.targetType = positional[0];
|
|
985
|
+
flags.targetId = positional[1];
|
|
986
|
+
}
|
|
987
|
+
|
|
827
988
|
// Interpolate path
|
|
828
989
|
let path = cmd.path;
|
|
829
990
|
const pathParams = [...path.matchAll(/:([A-Za-z][A-Za-z0-9_]*)/g)].map((match) => match[1]);
|
|
830
991
|
if (pathParams.length > 0) {
|
|
831
|
-
pathParams.
|
|
832
|
-
|
|
992
|
+
for (const [index, paramName] of pathParams.entries()) {
|
|
993
|
+
let value = positional[index];
|
|
833
994
|
if (!value) {
|
|
834
995
|
const ordinal = index === 0 ? 'an ID argument' : `argument ${index + 1} for :${paramName}`;
|
|
835
996
|
console.error(`Command '${commandKey}' requires ${ordinal}.`);
|
|
836
997
|
exitGracefully(1);
|
|
837
998
|
}
|
|
999
|
+
value = await resolveNameParam(commandKey, paramName, value, flags);
|
|
838
1000
|
path = path.replace(`:${paramName}`, value);
|
|
839
|
-
}
|
|
1001
|
+
}
|
|
840
1002
|
}
|
|
841
1003
|
|
|
842
1004
|
// Append query parameters for GET commands with filters
|
|
@@ -855,6 +1017,11 @@ if (cmd.queryParams || cmd.fixedQuery) {
|
|
|
855
1017
|
if (qs) path += (path.includes('?') ? '&' : '?') + qs;
|
|
856
1018
|
}
|
|
857
1019
|
|
|
1020
|
+
if (commandKey.startsWith('smoke.') && (flags.write === 'true' || flags.send === 'true')) {
|
|
1021
|
+
console.error(`Command '${commandKey}' is read-only; --write/--send are not supported for this smoke check.`);
|
|
1022
|
+
exitGracefully(2);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
858
1025
|
// Build body from flags or fixedBody
|
|
859
1026
|
let body = undefined;
|
|
860
1027
|
if (cmd.fixedBody) {
|
|
@@ -884,6 +1051,13 @@ if (supportsCommentContentInput(commandKey) && !body && positional[pathParams.le
|
|
|
884
1051
|
body = { content: normalizeCliMultiline(positional.slice(pathParams.length).join(' ')) };
|
|
885
1052
|
}
|
|
886
1053
|
|
|
1054
|
+
if (flags['dry-run'] === 'true' && ['POST', 'PATCH', 'DELETE'].includes(cmd.method)) {
|
|
1055
|
+
console.log(`Dry run: ${cmd.method} ${path}`);
|
|
1056
|
+
if (body) console.log(COMPACT_JSON ? JSON.stringify(body) : JSON.stringify(body, null, 2));
|
|
1057
|
+
else console.log('No request body.');
|
|
1058
|
+
exitGracefully(0);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
887
1061
|
// ── Search Command ──
|
|
888
1062
|
if (commandKey === 'search') {
|
|
889
1063
|
const q = [id, ...positional.slice(1)].filter(Boolean).join(' ');
|
|
@@ -891,8 +1065,13 @@ if (commandKey === 'search') {
|
|
|
891
1065
|
console.error('Usage: search <term>');
|
|
892
1066
|
exitGracefully(1);
|
|
893
1067
|
}
|
|
894
|
-
const
|
|
895
|
-
const
|
|
1068
|
+
const params = new URLSearchParams({ q });
|
|
1069
|
+
for (const key of ['client', 'clientId', 'project', 'projectId', 'type', 'limit']) {
|
|
1070
|
+
if (flags[key] !== undefined) params.set(key, flags[key]);
|
|
1071
|
+
}
|
|
1072
|
+
const data = await api('GET', `/api/admin/search?${params.toString()}`);
|
|
1073
|
+
const resultGroups = ['clients', 'projects', 'tasks', 'updates', 'comments', 'notes', 'docs', 'capacity'];
|
|
1074
|
+
const hasResults = resultGroups.some((group) => (data[group] || []).length > 0);
|
|
896
1075
|
|
|
897
1076
|
if (!hasResults) {
|
|
898
1077
|
console.log(`No results for "${q}"`);
|
|
@@ -902,7 +1081,15 @@ if (commandKey === 'search') {
|
|
|
902
1081
|
console.log(`\nSearch: "${q}"`);
|
|
903
1082
|
console.log('─'.repeat(50));
|
|
904
1083
|
|
|
905
|
-
if (data.
|
|
1084
|
+
if (data.clients?.length > 0) {
|
|
1085
|
+
console.log('\nClients:');
|
|
1086
|
+
data.clients.forEach((c) => {
|
|
1087
|
+
const company = c.company ? ` (${c.company})` : '';
|
|
1088
|
+
console.log(` • ${c.name}${company} [${c.status}] [${c.id}]`);
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
if ((data.projects || []).length > 0) {
|
|
906
1093
|
console.log('\nProjects:');
|
|
907
1094
|
data.projects.forEach((p) => {
|
|
908
1095
|
const visibility = p.visibility ? ` [${p.visibility}]` : '';
|
|
@@ -912,7 +1099,7 @@ if (commandKey === 'search') {
|
|
|
912
1099
|
console.log('\nProjects: (none)');
|
|
913
1100
|
}
|
|
914
1101
|
|
|
915
|
-
if (data.tasks.length > 0) {
|
|
1102
|
+
if ((data.tasks || []).length > 0) {
|
|
916
1103
|
console.log('\nTasks:');
|
|
917
1104
|
data.tasks.forEach((t) => {
|
|
918
1105
|
const prio = t.priority && t.priority !== 'normal' ? ` (${t.priority})` : '';
|
|
@@ -922,7 +1109,7 @@ if (commandKey === 'search') {
|
|
|
922
1109
|
console.log('\nTasks: (none)');
|
|
923
1110
|
}
|
|
924
1111
|
|
|
925
|
-
if (data.updates.length > 0) {
|
|
1112
|
+
if ((data.updates || []).length > 0) {
|
|
926
1113
|
console.log('\nUpdates:');
|
|
927
1114
|
data.updates.forEach((u) => {
|
|
928
1115
|
const vis = u.visibility === 'internal' ? ' [INTERNAL]' : '';
|
|
@@ -932,6 +1119,16 @@ if (commandKey === 'search') {
|
|
|
932
1119
|
console.log('\nUpdates: (none)');
|
|
933
1120
|
}
|
|
934
1121
|
|
|
1122
|
+
for (const [label, key] of [['Comments', 'comments'], ['Notes', 'notes'], ['Docs', 'docs'], ['Capacity', 'capacity']]) {
|
|
1123
|
+
const items = data[key] || [];
|
|
1124
|
+
if (items.length === 0) continue;
|
|
1125
|
+
console.log(`\n${label}:`);
|
|
1126
|
+
items.forEach((item) => {
|
|
1127
|
+
const text = item.title || item.contentPreview || item.documentNumber || item.documentType || item.status || item.billableStatus || item.id;
|
|
1128
|
+
console.log(` • ${text} [${item.id}]`);
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
|
|
935
1132
|
exitGracefully(0);
|
|
936
1133
|
}
|
|
937
1134
|
|