@klevar/portal-cli 0.1.20 → 0.1.22
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 +138 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/operator.d.ts +138 -0
- package/dist/commands/operator.js +139 -0
- package/dist/commands/operator.js.map +1 -0
- package/dist/lib/legacy-runner.js +217 -10
- 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,144 @@ 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
|
+
queryParams: string[];
|
|
584
|
+
};
|
|
585
|
+
'smoke.portal': {
|
|
586
|
+
method: "GET";
|
|
587
|
+
path: string;
|
|
588
|
+
auth: "apiKey";
|
|
589
|
+
description: string;
|
|
590
|
+
};
|
|
591
|
+
'smoke.docs': {
|
|
592
|
+
method: "GET";
|
|
593
|
+
path: string;
|
|
594
|
+
auth: "apiKey";
|
|
595
|
+
description: string;
|
|
596
|
+
};
|
|
597
|
+
'smoke.capacity': {
|
|
598
|
+
method: "GET";
|
|
599
|
+
path: string;
|
|
600
|
+
auth: "apiKey";
|
|
601
|
+
description: string;
|
|
602
|
+
};
|
|
603
|
+
'smoke.recurring': {
|
|
604
|
+
method: "GET";
|
|
605
|
+
path: string;
|
|
606
|
+
auth: "apiKey";
|
|
607
|
+
description: string;
|
|
608
|
+
};
|
|
609
|
+
'smoke.notifications': {
|
|
610
|
+
method: "GET";
|
|
611
|
+
path: string;
|
|
612
|
+
auth: "apiKey";
|
|
613
|
+
description: string;
|
|
614
|
+
};
|
|
615
|
+
'clients.notifications.get': {
|
|
616
|
+
method: "GET";
|
|
617
|
+
path: string;
|
|
618
|
+
auth: "apiKey";
|
|
619
|
+
description: string;
|
|
620
|
+
};
|
|
621
|
+
'clients.notifications.update': {
|
|
622
|
+
method: "PATCH";
|
|
623
|
+
path: string;
|
|
624
|
+
auth: "apiKey";
|
|
625
|
+
description: string;
|
|
626
|
+
body: string[];
|
|
627
|
+
};
|
|
628
|
+
'projects.notifications.get': {
|
|
629
|
+
method: "GET";
|
|
630
|
+
path: string;
|
|
631
|
+
auth: "apiKey";
|
|
632
|
+
description: string;
|
|
633
|
+
};
|
|
634
|
+
'projects.notifications.update': {
|
|
635
|
+
method: "PATCH";
|
|
636
|
+
path: string;
|
|
637
|
+
auth: "apiKey";
|
|
638
|
+
description: string;
|
|
639
|
+
body: string[];
|
|
640
|
+
};
|
|
641
|
+
'notifications.preview': {
|
|
642
|
+
method: "GET";
|
|
643
|
+
path: string;
|
|
644
|
+
auth: "apiKey";
|
|
645
|
+
description: string;
|
|
646
|
+
queryParams: string[];
|
|
647
|
+
};
|
|
648
|
+
'audit.list': {
|
|
649
|
+
method: "GET";
|
|
650
|
+
path: string;
|
|
651
|
+
auth: "apiKey";
|
|
652
|
+
description: string;
|
|
653
|
+
queryParams: string[];
|
|
654
|
+
};
|
|
655
|
+
'audit.target': {
|
|
656
|
+
method: "GET";
|
|
657
|
+
path: string;
|
|
658
|
+
auth: "apiKey";
|
|
659
|
+
description: string;
|
|
660
|
+
queryParams: string[];
|
|
661
|
+
};
|
|
662
|
+
};
|
|
525
663
|
notes: {
|
|
526
664
|
'notes.list': {
|
|
527
665
|
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,138 @@
|
|
|
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
|
+
queryParams: string[];
|
|
60
|
+
};
|
|
61
|
+
'smoke.portal': {
|
|
62
|
+
method: "GET";
|
|
63
|
+
path: string;
|
|
64
|
+
auth: "apiKey";
|
|
65
|
+
description: string;
|
|
66
|
+
};
|
|
67
|
+
'smoke.docs': {
|
|
68
|
+
method: "GET";
|
|
69
|
+
path: string;
|
|
70
|
+
auth: "apiKey";
|
|
71
|
+
description: string;
|
|
72
|
+
};
|
|
73
|
+
'smoke.capacity': {
|
|
74
|
+
method: "GET";
|
|
75
|
+
path: string;
|
|
76
|
+
auth: "apiKey";
|
|
77
|
+
description: string;
|
|
78
|
+
};
|
|
79
|
+
'smoke.recurring': {
|
|
80
|
+
method: "GET";
|
|
81
|
+
path: string;
|
|
82
|
+
auth: "apiKey";
|
|
83
|
+
description: string;
|
|
84
|
+
};
|
|
85
|
+
'smoke.notifications': {
|
|
86
|
+
method: "GET";
|
|
87
|
+
path: string;
|
|
88
|
+
auth: "apiKey";
|
|
89
|
+
description: string;
|
|
90
|
+
};
|
|
91
|
+
'clients.notifications.get': {
|
|
92
|
+
method: "GET";
|
|
93
|
+
path: string;
|
|
94
|
+
auth: "apiKey";
|
|
95
|
+
description: string;
|
|
96
|
+
};
|
|
97
|
+
'clients.notifications.update': {
|
|
98
|
+
method: "PATCH";
|
|
99
|
+
path: string;
|
|
100
|
+
auth: "apiKey";
|
|
101
|
+
description: string;
|
|
102
|
+
body: string[];
|
|
103
|
+
};
|
|
104
|
+
'projects.notifications.get': {
|
|
105
|
+
method: "GET";
|
|
106
|
+
path: string;
|
|
107
|
+
auth: "apiKey";
|
|
108
|
+
description: string;
|
|
109
|
+
};
|
|
110
|
+
'projects.notifications.update': {
|
|
111
|
+
method: "PATCH";
|
|
112
|
+
path: string;
|
|
113
|
+
auth: "apiKey";
|
|
114
|
+
description: string;
|
|
115
|
+
body: string[];
|
|
116
|
+
};
|
|
117
|
+
'notifications.preview': {
|
|
118
|
+
method: "GET";
|
|
119
|
+
path: string;
|
|
120
|
+
auth: "apiKey";
|
|
121
|
+
description: string;
|
|
122
|
+
queryParams: string[];
|
|
123
|
+
};
|
|
124
|
+
'audit.list': {
|
|
125
|
+
method: "GET";
|
|
126
|
+
path: string;
|
|
127
|
+
auth: "apiKey";
|
|
128
|
+
description: string;
|
|
129
|
+
queryParams: string[];
|
|
130
|
+
};
|
|
131
|
+
'audit.target': {
|
|
132
|
+
method: "GET";
|
|
133
|
+
path: string;
|
|
134
|
+
auth: "apiKey";
|
|
135
|
+
description: string;
|
|
136
|
+
queryParams: string[];
|
|
137
|
+
};
|
|
138
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
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; optionally scope with --project',
|
|
38
|
+
queryParams: ['period', 'projectId|project'],
|
|
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; exits 1 only for critical unless --no-fail or --warn-only is set',
|
|
59
|
+
queryParams: ['noFail|no-fail', 'warnOnly|warn-only'],
|
|
60
|
+
},
|
|
61
|
+
'smoke.portal': {
|
|
62
|
+
method: 'GET',
|
|
63
|
+
path: '/api/admin/clients/:id',
|
|
64
|
+
auth: 'apiKey',
|
|
65
|
+
description: 'Read-only portal smoke check',
|
|
66
|
+
},
|
|
67
|
+
'smoke.docs': {
|
|
68
|
+
method: 'GET',
|
|
69
|
+
path: '/api/admin/clients/:id/docs/documents',
|
|
70
|
+
auth: 'apiKey',
|
|
71
|
+
description: 'Read-only Docs smoke check',
|
|
72
|
+
},
|
|
73
|
+
'smoke.capacity': {
|
|
74
|
+
method: 'GET',
|
|
75
|
+
path: '/api/admin/projects/:projectId/capacity-summary',
|
|
76
|
+
auth: 'apiKey',
|
|
77
|
+
description: 'Read-only capacity smoke check',
|
|
78
|
+
},
|
|
79
|
+
'smoke.recurring': {
|
|
80
|
+
method: 'GET',
|
|
81
|
+
path: '/api/admin/projects/:projectId/recurring-checkpoints',
|
|
82
|
+
auth: 'apiKey',
|
|
83
|
+
description: 'Read-only recurring smoke check',
|
|
84
|
+
},
|
|
85
|
+
'smoke.notifications': {
|
|
86
|
+
method: 'GET',
|
|
87
|
+
path: '/api/admin/smoke/notifications/:clientId',
|
|
88
|
+
auth: 'apiKey',
|
|
89
|
+
description: 'Read-only notification smoke check',
|
|
90
|
+
},
|
|
91
|
+
'clients.notifications.get': {
|
|
92
|
+
method: 'GET',
|
|
93
|
+
path: '/api/admin/clients/:id/notification-preferences',
|
|
94
|
+
auth: 'apiKey',
|
|
95
|
+
description: 'Show client notification preferences',
|
|
96
|
+
},
|
|
97
|
+
'clients.notifications.update': {
|
|
98
|
+
method: 'PATCH',
|
|
99
|
+
path: '/api/admin/clients/:id/notification-preferences',
|
|
100
|
+
auth: 'apiKey',
|
|
101
|
+
description: 'Update client notification preferences',
|
|
102
|
+
body: ['mode', 'digestFrequency'],
|
|
103
|
+
},
|
|
104
|
+
'projects.notifications.get': {
|
|
105
|
+
method: 'GET',
|
|
106
|
+
path: '/api/admin/projects/:id/notification-preferences',
|
|
107
|
+
auth: 'apiKey',
|
|
108
|
+
description: 'Show project notification preferences',
|
|
109
|
+
},
|
|
110
|
+
'projects.notifications.update': {
|
|
111
|
+
method: 'PATCH',
|
|
112
|
+
path: '/api/admin/projects/:id/notification-preferences',
|
|
113
|
+
auth: 'apiKey',
|
|
114
|
+
description: 'Update project notification preferences',
|
|
115
|
+
body: ['mode', 'digestFrequency'],
|
|
116
|
+
},
|
|
117
|
+
'notifications.preview': {
|
|
118
|
+
method: 'GET',
|
|
119
|
+
path: '/api/admin/notifications/preview/:eventType',
|
|
120
|
+
auth: 'apiKey',
|
|
121
|
+
description: 'Preview notification rendering without sending',
|
|
122
|
+
queryParams: ['clientId|client', 'projectId|project'],
|
|
123
|
+
},
|
|
124
|
+
'audit.list': {
|
|
125
|
+
method: 'GET',
|
|
126
|
+
path: '/api/admin/audit-events',
|
|
127
|
+
auth: 'apiKey',
|
|
128
|
+
description: 'List operational audit events',
|
|
129
|
+
queryParams: ['clientId|client', 'projectId|project', 'actorId|actor', 'action', 'targetType', 'targetId', 'since', 'until', 'limit'],
|
|
130
|
+
},
|
|
131
|
+
'audit.target': {
|
|
132
|
+
method: 'GET',
|
|
133
|
+
path: '/api/admin/audit-events',
|
|
134
|
+
auth: 'apiKey',
|
|
135
|
+
description: 'List audit events for one target',
|
|
136
|
+
queryParams: ['targetType', 'targetId', 'limit'],
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
//# 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,50 @@ 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
|
+
if (paramName === 'id' && (commandKey === 'smoke.portal' || commandKey === 'smoke.docs')) return 'client';
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async function resolveNameParam(commandKey, paramName, value, flags) {
|
|
320
|
+
if (!value || looksLikeOpaqueId(value)) return value;
|
|
321
|
+
const entity = pathParamEntity(commandKey, paramName);
|
|
322
|
+
if (!entity) return value;
|
|
323
|
+
const params = new URLSearchParams({ q: value, type: entity, limit: '10' });
|
|
324
|
+
if (entity === 'project' && flags.clientId) params.set('clientId', flags.clientId);
|
|
325
|
+
else if (entity === 'project' && flags.client) params.set('client', flags.client);
|
|
326
|
+
const data = await api('GET', `/api/admin/search?${params.toString()}`);
|
|
327
|
+
const rows = entity === 'client' ? (data.clients || []) : (data.projects || []);
|
|
328
|
+
const exact = rows.filter((row) => (row.name || '').toLowerCase() === value.toLowerCase());
|
|
329
|
+
const candidates = exact.length > 0 ? exact : rows;
|
|
330
|
+
if (candidates.length === 1) return candidates[0].id;
|
|
331
|
+
if (candidates.length === 0) console.error(`No ${entity} found for "${value}".`);
|
|
332
|
+
else {
|
|
333
|
+
console.error(`Ambiguous ${entity} name "${value}". Use an ID or narrow the search.`);
|
|
334
|
+
for (const row of candidates.slice(0, 5)) console.error(` ${row.name} [${row.id}]`);
|
|
335
|
+
}
|
|
336
|
+
exitGracefully(2);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async function resolveQueryNameParam(commandKey, canonical, value, flags) {
|
|
340
|
+
if (!value || looksLikeOpaqueId(value)) return value;
|
|
341
|
+
if (canonical === 'clientId') return resolveNameParam(commandKey, 'clientId', value, flags);
|
|
342
|
+
if (canonical === 'projectId') return resolveNameParam(commandKey, 'projectId', value, flags);
|
|
343
|
+
return value;
|
|
344
|
+
}
|
|
345
|
+
|
|
302
346
|
const HELP_ENUMS = {
|
|
303
347
|
priority: 'low|normal|high|urgent',
|
|
304
348
|
submittedBy: 'client|admin|va|system',
|
|
@@ -323,6 +367,8 @@ const HELP_ENUMS = {
|
|
|
323
367
|
owner: 'admin|client|shared',
|
|
324
368
|
requiresClientAcceptance: 'true|false',
|
|
325
369
|
requiresAdminAcceptance: 'true|false',
|
|
370
|
+
mode: 'muted|portal_only|admin_only|material_updates|digest|all',
|
|
371
|
+
digestFrequency: 'daily|weekly|monthly',
|
|
326
372
|
};
|
|
327
373
|
|
|
328
374
|
function helpFlag(commandKey, field) {
|
|
@@ -356,6 +402,11 @@ function helpQueryFlag(field) {
|
|
|
356
402
|
// ── Output Formatting ───────────────────────────────────────────
|
|
357
403
|
|
|
358
404
|
function formatOutput(data, commandKey) {
|
|
405
|
+
if (commandKey === 'ops-health' && OUTPUT_JSON) {
|
|
406
|
+
console.log(COMPACT_JSON ? JSON.stringify(data) : JSON.stringify(data, null, 2));
|
|
407
|
+
if (data.status === 'critical' && flags.noFail !== 'true' && flags['no-fail'] !== 'true' && flags.warnOnly !== 'true' && flags['warn-only'] !== 'true') exitGracefully(1);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
359
410
|
if (OUTPUT_JSON) {
|
|
360
411
|
console.log(COMPACT_JSON ? JSON.stringify(data) : JSON.stringify(data, null, 2));
|
|
361
412
|
return;
|
|
@@ -422,6 +473,111 @@ function formatOutput(data, commandKey) {
|
|
|
422
473
|
return;
|
|
423
474
|
}
|
|
424
475
|
|
|
476
|
+
if (commandKey === 'inbox') {
|
|
477
|
+
const sections = data.sections || {};
|
|
478
|
+
console.log('\nOperator Inbox');
|
|
479
|
+
console.log('-'.repeat(80));
|
|
480
|
+
for (const [key, section] of Object.entries(sections)) {
|
|
481
|
+
const items = section.items || [];
|
|
482
|
+
if (items.length === 0) continue;
|
|
483
|
+
console.log(`\n${key} (${items.length})`);
|
|
484
|
+
for (const item of items) {
|
|
485
|
+
const unread = item.unread ? '*' : ' ';
|
|
486
|
+
const scope = [item.clientName, item.projectName].filter(Boolean).join(' / ');
|
|
487
|
+
console.log(` ${unread} ${item.summary} ${scope ? `- ${scope}` : ''} [${item.id}]`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (commandKey === 'reports.monthly') {
|
|
494
|
+
const report = data.report;
|
|
495
|
+
if (!report) { console.log(JSON.stringify(data, null, 2)); return; }
|
|
496
|
+
if (COMPACT_JSON) {
|
|
497
|
+
console.log(`${report.client.name}: ${report.period} - ${report.completedWork.length} done, ${report.openWork.length} open`);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
console.log(`\nMonthly Report: ${report.client.name} (${report.period})`);
|
|
501
|
+
console.log('-'.repeat(80));
|
|
502
|
+
console.log(`Completed work: ${report.completedWork.length}`);
|
|
503
|
+
for (const item of report.completedWork) console.log(` - ${item.title}`);
|
|
504
|
+
console.log(`Open work: ${report.openWork.length}`);
|
|
505
|
+
for (const item of report.openWork) console.log(` - ${item.title} [${item.status}]`);
|
|
506
|
+
console.log(`Updates: ${report.updates.length}`);
|
|
507
|
+
console.log(`Invoices: ${report.invoices.length}`);
|
|
508
|
+
console.log(`Capacity items: ${report.capacity.length}`);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (commandKey === 'client.timeline' || commandKey === 'project.timeline') {
|
|
513
|
+
const items = data.data || [];
|
|
514
|
+
if (items.length === 0) { console.log('No timeline events found.'); return; }
|
|
515
|
+
console.log(`\nTimeline (${items.length})`);
|
|
516
|
+
console.log('-'.repeat(80));
|
|
517
|
+
for (const item of items) {
|
|
518
|
+
const scope = [item.clientName, item.projectName].filter(Boolean).join(' / ');
|
|
519
|
+
console.log(` ${item.type}: ${item.summary}${scope ? ` - ${scope}` : ''} [${item.sourceId}]`);
|
|
520
|
+
}
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (commandKey === 'ops-health') {
|
|
525
|
+
console.log(`Operational health: ${data.status}`);
|
|
526
|
+
for (const [key, value] of Object.entries(data.failures || {})) {
|
|
527
|
+
console.log(` ${key}: ${value}`);
|
|
528
|
+
}
|
|
529
|
+
if (data.status === 'critical' && flags.noFail !== 'true' && flags['no-fail'] !== 'true' && flags.warnOnly !== 'true' && flags['warn-only'] !== 'true') exitGracefully(1);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (commandKey === 'smoke.notifications') {
|
|
534
|
+
const smoke = data.smoke || {};
|
|
535
|
+
console.log(`Notification smoke: ${smoke.client?.name || 'client'}`);
|
|
536
|
+
console.log(` Read-only dry run: ${smoke.dryRun === false ? 'false' : 'true'}`);
|
|
537
|
+
console.log(` notificationsEnabled: ${smoke.client?.notificationsEnabled}`);
|
|
538
|
+
console.log(` preference: ${smoke.preference?.mode || 'n/a'}`);
|
|
539
|
+
console.log(` failed deliveries: ${smoke.failedCount ?? 0}`);
|
|
540
|
+
console.log(' Would send: none');
|
|
541
|
+
console.log(' Would create: none');
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (
|
|
546
|
+
commandKey === 'clients.notifications.get' ||
|
|
547
|
+
commandKey === 'clients.notifications.update' ||
|
|
548
|
+
commandKey === 'projects.notifications.get' ||
|
|
549
|
+
commandKey === 'projects.notifications.update'
|
|
550
|
+
) {
|
|
551
|
+
const preference = data.preference || {};
|
|
552
|
+
console.log(`Notification preference: ${preference.mode || 'n/a'}`);
|
|
553
|
+
if (preference.digestFrequency) console.log(` Digest: ${preference.digestFrequency}`);
|
|
554
|
+
if (preference.inheritedFromClient) console.log(' Inherited from client preference.');
|
|
555
|
+
if (preference.inheritedFromNotificationsEnabled) console.log(' Inherited from notificationsEnabled.');
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (commandKey === 'notifications.preview') {
|
|
560
|
+
const preview = data.preview || {};
|
|
561
|
+
console.log(`Notification preview: ${preview.subject || preview.eventType}`);
|
|
562
|
+
console.log(` Audience: ${(preview.audience || []).join(', ') || 'none'}`);
|
|
563
|
+
console.log(` Mode: ${preview.mode || 'n/a'}`);
|
|
564
|
+
console.log(` Thread: ${preview.threadKey || 'n/a'}`);
|
|
565
|
+
console.log('');
|
|
566
|
+
console.log(preview.body || '');
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (commandKey === 'audit.list' || commandKey === 'audit.target') {
|
|
571
|
+
const items = data.data || [];
|
|
572
|
+
if (items.length === 0) { console.log('No audit events found. Audit records operator actions from this release forward; older actions are not backfilled.'); return; }
|
|
573
|
+
console.log(`\nAudit Events (${items.length})`);
|
|
574
|
+
console.log('-'.repeat(80));
|
|
575
|
+
for (const item of items) {
|
|
576
|
+
console.log(` ${item.action}: ${item.targetType}/${item.targetId} [${item.id}]`);
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
|
|
425
581
|
if (commandKey === 'projects.get') {
|
|
426
582
|
const p = data.project;
|
|
427
583
|
console.log(`\n${p.name} [${p.status}]`);
|
|
@@ -778,6 +934,11 @@ if (!resource || resource === 'help' || resource === '--help') {
|
|
|
778
934
|
}
|
|
779
935
|
console.log(`\nConfig: PORTAL_API_URL, PORTAL_API_KEY, PORTAL_TOKEN (or ~/.klevar/portal.env)`);
|
|
780
936
|
console.log(`Target: ${BASE_URL}`);
|
|
937
|
+
console.log('\nExamples:');
|
|
938
|
+
console.log(' klevar-portal inbox --unread --compact');
|
|
939
|
+
console.log(' klevar-portal client timeline "Acme Ltd" --type task');
|
|
940
|
+
console.log(' klevar-portal notifications preview project.status_changed --client "Acme Ltd" --project "Retainer"');
|
|
941
|
+
console.log(' klevar-portal audit target task <taskId>');
|
|
781
942
|
exitGracefully(0);
|
|
782
943
|
}
|
|
783
944
|
|
|
@@ -827,19 +988,25 @@ if (supportsCommentContentInput(commandKey)) {
|
|
|
827
988
|
}
|
|
828
989
|
}
|
|
829
990
|
|
|
991
|
+
if (commandKey === 'audit.target' && positional.length >= 2) {
|
|
992
|
+
flags.targetType = positional[0];
|
|
993
|
+
flags.targetId = positional[1];
|
|
994
|
+
}
|
|
995
|
+
|
|
830
996
|
// Interpolate path
|
|
831
997
|
let path = cmd.path;
|
|
832
998
|
const pathParams = [...path.matchAll(/:([A-Za-z][A-Za-z0-9_]*)/g)].map((match) => match[1]);
|
|
833
999
|
if (pathParams.length > 0) {
|
|
834
|
-
pathParams.
|
|
835
|
-
|
|
1000
|
+
for (const [index, paramName] of pathParams.entries()) {
|
|
1001
|
+
let value = positional[index];
|
|
836
1002
|
if (!value) {
|
|
837
1003
|
const ordinal = index === 0 ? 'an ID argument' : `argument ${index + 1} for :${paramName}`;
|
|
838
1004
|
console.error(`Command '${commandKey}' requires ${ordinal}.`);
|
|
839
1005
|
exitGracefully(1);
|
|
840
1006
|
}
|
|
1007
|
+
value = await resolveNameParam(commandKey, paramName, value, flags);
|
|
841
1008
|
path = path.replace(`:${paramName}`, value);
|
|
842
|
-
}
|
|
1009
|
+
}
|
|
843
1010
|
}
|
|
844
1011
|
|
|
845
1012
|
// Append query parameters for GET commands with filters
|
|
@@ -851,13 +1018,23 @@ if (cmd.queryParams || cmd.fixedQuery) {
|
|
|
851
1018
|
for (const key of cmd.queryParams || []) {
|
|
852
1019
|
const aliases = key.split('|');
|
|
853
1020
|
const canonical = aliases[0];
|
|
854
|
-
|
|
855
|
-
if (value !== undefined)
|
|
1021
|
+
let value = aliases.map((alias) => flags[alias]).find((candidate) => candidate !== undefined);
|
|
1022
|
+
if (value !== undefined) {
|
|
1023
|
+
value = await resolveQueryNameParam(commandKey, canonical, value, flags);
|
|
1024
|
+
flags[canonical] = value;
|
|
1025
|
+
for (const alias of aliases) flags[alias] = value;
|
|
1026
|
+
params.set(canonical, value);
|
|
1027
|
+
}
|
|
856
1028
|
}
|
|
857
1029
|
const qs = params.toString();
|
|
858
1030
|
if (qs) path += (path.includes('?') ? '&' : '?') + qs;
|
|
859
1031
|
}
|
|
860
1032
|
|
|
1033
|
+
if (commandKey.startsWith('smoke.') && (flags.write === 'true' || flags.send === 'true')) {
|
|
1034
|
+
console.error(`Command '${commandKey}' is read-only; --write/--send are not supported for this smoke check.`);
|
|
1035
|
+
exitGracefully(2);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
861
1038
|
// Build body from flags or fixedBody
|
|
862
1039
|
let body = undefined;
|
|
863
1040
|
if (cmd.fixedBody) {
|
|
@@ -887,6 +1064,13 @@ if (supportsCommentContentInput(commandKey) && !body && positional[pathParams.le
|
|
|
887
1064
|
body = { content: normalizeCliMultiline(positional.slice(pathParams.length).join(' ')) };
|
|
888
1065
|
}
|
|
889
1066
|
|
|
1067
|
+
if (flags['dry-run'] === 'true' && ['POST', 'PATCH', 'DELETE'].includes(cmd.method)) {
|
|
1068
|
+
console.log(`Dry run: ${cmd.method} ${path}`);
|
|
1069
|
+
if (body) console.log(COMPACT_JSON ? JSON.stringify(body) : JSON.stringify(body, null, 2));
|
|
1070
|
+
else console.log('No request body.');
|
|
1071
|
+
exitGracefully(0);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
890
1074
|
// ── Search Command ──
|
|
891
1075
|
if (commandKey === 'search') {
|
|
892
1076
|
const q = [id, ...positional.slice(1)].filter(Boolean).join(' ');
|
|
@@ -894,8 +1078,13 @@ if (commandKey === 'search') {
|
|
|
894
1078
|
console.error('Usage: search <term>');
|
|
895
1079
|
exitGracefully(1);
|
|
896
1080
|
}
|
|
897
|
-
const
|
|
898
|
-
const
|
|
1081
|
+
const params = new URLSearchParams({ q });
|
|
1082
|
+
for (const key of ['client', 'clientId', 'project', 'projectId', 'type', 'limit']) {
|
|
1083
|
+
if (flags[key] !== undefined) params.set(key, flags[key]);
|
|
1084
|
+
}
|
|
1085
|
+
const data = await api('GET', `/api/admin/search?${params.toString()}`);
|
|
1086
|
+
const resultGroups = ['clients', 'projects', 'tasks', 'updates', 'comments', 'notes', 'docs', 'capacity'];
|
|
1087
|
+
const hasResults = resultGroups.some((group) => (data[group] || []).length > 0);
|
|
899
1088
|
|
|
900
1089
|
if (!hasResults) {
|
|
901
1090
|
console.log(`No results for "${q}"`);
|
|
@@ -905,7 +1094,15 @@ if (commandKey === 'search') {
|
|
|
905
1094
|
console.log(`\nSearch: "${q}"`);
|
|
906
1095
|
console.log('─'.repeat(50));
|
|
907
1096
|
|
|
908
|
-
if (data.
|
|
1097
|
+
if (data.clients?.length > 0) {
|
|
1098
|
+
console.log('\nClients:');
|
|
1099
|
+
data.clients.forEach((c) => {
|
|
1100
|
+
const company = c.company ? ` (${c.company})` : '';
|
|
1101
|
+
console.log(` • ${c.name}${company} [${c.status}] [${c.id}]`);
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
if ((data.projects || []).length > 0) {
|
|
909
1106
|
console.log('\nProjects:');
|
|
910
1107
|
data.projects.forEach((p) => {
|
|
911
1108
|
const visibility = p.visibility ? ` [${p.visibility}]` : '';
|
|
@@ -915,7 +1112,7 @@ if (commandKey === 'search') {
|
|
|
915
1112
|
console.log('\nProjects: (none)');
|
|
916
1113
|
}
|
|
917
1114
|
|
|
918
|
-
if (data.tasks.length > 0) {
|
|
1115
|
+
if ((data.tasks || []).length > 0) {
|
|
919
1116
|
console.log('\nTasks:');
|
|
920
1117
|
data.tasks.forEach((t) => {
|
|
921
1118
|
const prio = t.priority && t.priority !== 'normal' ? ` (${t.priority})` : '';
|
|
@@ -925,7 +1122,7 @@ if (commandKey === 'search') {
|
|
|
925
1122
|
console.log('\nTasks: (none)');
|
|
926
1123
|
}
|
|
927
1124
|
|
|
928
|
-
if (data.updates.length > 0) {
|
|
1125
|
+
if ((data.updates || []).length > 0) {
|
|
929
1126
|
console.log('\nUpdates:');
|
|
930
1127
|
data.updates.forEach((u) => {
|
|
931
1128
|
const vis = u.visibility === 'internal' ? ' [INTERNAL]' : '';
|
|
@@ -935,6 +1132,16 @@ if (commandKey === 'search') {
|
|
|
935
1132
|
console.log('\nUpdates: (none)');
|
|
936
1133
|
}
|
|
937
1134
|
|
|
1135
|
+
for (const [label, key] of [['Comments', 'comments'], ['Notes', 'notes'], ['Docs', 'docs'], ['Capacity', 'capacity']]) {
|
|
1136
|
+
const items = data[key] || [];
|
|
1137
|
+
if (items.length === 0) continue;
|
|
1138
|
+
console.log(`\n${label}:`);
|
|
1139
|
+
items.forEach((item) => {
|
|
1140
|
+
const text = item.title || item.contentPreview || item.documentNumber || item.documentType || item.status || item.billableStatus || item.id;
|
|
1141
|
+
console.log(` • ${text} [${item.id}]`);
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
|
|
938
1145
|
exitGracefully(0);
|
|
939
1146
|
}
|
|
940
1147
|
|