@klevar/portal-cli 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,6 +54,9 @@ npx @klevar/portal-cli capacity update <budgetId> --capacityAmount 20
54
54
  npx @klevar/portal-cli capacity summary <projectId> --period 2026-06
55
55
  npx @klevar/portal-cli capacity budget-summary <budgetId> --period 2026-06
56
56
  npx @klevar/portal-cli capacity report <projectId> --period 2026-06
57
+ npx @klevar/portal-cli capacity notifications <budgetId>
58
+ npx @klevar/portal-cli capacity notifications-update <budgetId> --notifyAtWarning true --warningThresholdPct 80 --notifyAtCap true --notifyOverCap true --notifyClient false --notifyAdmin true
59
+ npx @klevar/portal-cli capacity notification-state <budgetId> --period 2026-06
57
60
  npx @klevar/portal-cli capacity pause <budgetId>
58
61
  npx @klevar/portal-cli capacity resume <budgetId>
59
62
  npx @klevar/portal-cli capacity end <budgetId>
@@ -84,6 +87,16 @@ Supported `visibility` values:
84
87
  - `client_visible_summary`: client can see summary totals only.
85
88
  - `client_visible_detail`: client can see summary totals and visible usage entries.
86
89
 
90
+ Capacity notification flags are writable on `capacity create`, `capacity update`, and `capacity notifications-update`:
91
+
92
+ - `notifyAtWarning`: default `true`.
93
+ - `notifyAtCap`: default `true`.
94
+ - `notifyOverCap`: default `false`.
95
+ - `notifyOnReset`: stored for future reset notifications; no scheduler is active yet.
96
+ - `notifyClient`: default `false`; client capacity emails require explicit opt-in and non-internal visibility.
97
+ - `notifyAdmin`: default `true`.
98
+ - `warningThresholdPct`: default `80`.
99
+
87
100
  Validation failures print API field details when the server returns them, for example:
88
101
 
89
102
  ```text
@@ -25,6 +25,26 @@ export declare const capacityCommands: {
25
25
  description: string;
26
26
  body: string[];
27
27
  };
28
+ 'capacity.notifications': {
29
+ method: "GET";
30
+ path: string;
31
+ auth: "apiKey";
32
+ description: string;
33
+ };
34
+ 'capacity.notifications-update': {
35
+ method: "PATCH";
36
+ path: string;
37
+ auth: "apiKey";
38
+ description: string;
39
+ body: string[];
40
+ };
41
+ 'capacity.notification-state': {
42
+ method: "GET";
43
+ path: string;
44
+ auth: "apiKey";
45
+ description: string;
46
+ queryParams: string[];
47
+ };
28
48
  'capacity.pause': {
29
49
  method: "POST";
30
50
  path: string;
@@ -1,20 +1,28 @@
1
1
  const budgetBody = [
2
2
  'name', 'description', 'clientId', 'laneKey', 'unitType', 'customUnitLabel',
3
3
  'periodType', 'periodStartDay', 'startDate', 'endDate', 'capacityAmount',
4
- 'warningThresholdPct', 'hardCap', 'allowOverage', 'overagePolicy',
4
+ 'warningThresholdPct', 'notifyAtWarning', 'notifyAtCap', 'notifyOverCap',
5
+ 'notifyOnReset', 'notifyClient', 'notifyAdmin', 'hardCap', 'allowOverage', 'overagePolicy',
5
6
  'resetBehavior', 'rolloverCapAmount', 'visibility', 'status', 'sortOrder',
6
7
  ];
8
+ const notificationBody = [
9
+ 'warningThresholdPct', 'notifyAtWarning', 'notifyAtCap', 'notifyOverCap',
10
+ 'notifyOnReset', 'notifyClient', 'notifyAdmin',
11
+ ];
7
12
  export const capacityCommands = {
8
13
  'capacity.list': { method: 'GET', path: '/api/admin/projects/:projectId/capacity-budgets', auth: 'apiKey', description: 'List project capacity budgets' },
9
14
  'capacity.get': { method: 'GET', path: '/api/admin/capacity-budgets/:id', auth: 'apiKey', description: 'Get a capacity budget' },
10
15
  'capacity.create': { method: 'POST', path: '/api/admin/projects/:projectId/capacity-budgets', auth: 'apiKey', description: 'Create a capacity budget; periodType monthly|weekly, unitType hours|credits, visibility internal_only|client_visible_summary|client_visible_detail', body: budgetBody },
11
16
  'capacity.update': { method: 'PATCH', path: '/api/admin/capacity-budgets/:id', auth: 'apiKey', description: 'Update a capacity budget; periodType monthly|weekly, unitType hours|credits, visibility internal_only|client_visible_summary|client_visible_detail', body: budgetBody },
17
+ 'capacity.notifications': { method: 'GET', path: '/api/admin/capacity-budgets/:id/notifications', auth: 'apiKey', description: 'Show capacity notification settings' },
18
+ 'capacity.notifications-update': { method: 'PATCH', path: '/api/admin/capacity-budgets/:id/notifications', auth: 'apiKey', description: 'Update capacity notification settings', body: notificationBody },
19
+ 'capacity.notification-state': { method: 'GET', path: '/api/admin/capacity-budgets/:id/notification-state', auth: 'apiKey', description: 'List capacity notification dedupe state', queryParams: ['period'] },
12
20
  'capacity.pause': { method: 'POST', path: '/api/admin/capacity-budgets/:id/pause', auth: 'apiKey', description: 'Pause a capacity budget' },
13
21
  'capacity.resume': { method: 'POST', path: '/api/admin/capacity-budgets/:id/resume', auth: 'apiKey', description: 'Resume a capacity budget' },
14
22
  'capacity.end': { method: 'POST', path: '/api/admin/capacity-budgets/:id/end', auth: 'apiKey', description: 'End a capacity budget' },
15
23
  'capacity.delete': { method: 'DELETE', path: '/api/admin/capacity-budgets/:id', auth: 'apiKey', description: 'Delete a capacity budget' },
16
24
  'capacity.summary': { method: 'GET', path: '/api/admin/projects/:projectId/capacity-summary', auth: 'apiKey', description: 'Project capacity summary', queryParams: ['period'] },
17
- 'capacity.client-summary': { method: 'GET', path: '/api/admin/clients/:clientId/capacity-summary', auth: 'apiKey', description: 'Client capacity summary', queryParams: ['period'] },
25
+ 'capacity.client-summary': { method: 'GET', path: '/api/admin/clients/:clientId/capacity-summary', auth: 'apiKey', description: 'Client capacity summary', queryParams: ['period', 'monthlyPeriod', 'weeklyPeriod'] },
18
26
  'capacity.budget-summary': { method: 'GET', path: '/api/admin/capacity-budgets/:id/summary', auth: 'apiKey', description: 'Budget capacity summary', queryParams: ['period'] },
19
27
  'capacity.report': { method: 'GET', path: '/api/admin/projects/:projectId/capacity-report', auth: 'apiKey', description: 'Project capacity report', queryParams: ['period'] },
20
28
  'capacity.portal-summary': { method: 'GET', path: '/api/portal/projects/:projectId/capacity-summary', auth: 'portalToken', description: 'Portal capacity summary', queryParams: ['period'] },
@@ -1 +1 @@
1
- {"version":3,"file":"capacity.js","sourceRoot":"","sources":["../../commands/capacity.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG;IACjB,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB;IAC3E,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB;IACxE,qBAAqB,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe;IACjE,eAAe,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW;CAC1E,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,iDAAiD,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE;IACzJ,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;IAChI,iBAAiB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,iDAAiD,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oJAAoJ,EAAE,IAAI,EAAE,UAAU,EAAE;IACnS,iBAAiB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oJAAoJ,EAAE,IAAI,EAAE,UAAU,EAAE;IACpR,gBAAgB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;IAC3I,iBAAiB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,wCAAwC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;IAC9I,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qCAAqC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;IACrI,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;IACzI,kBAAkB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,iDAAiD,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;IAChL,yBAAyB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,+CAA+C,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;IACpL,yBAAyB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,yCAAyC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;IAC9K,iBAAiB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gDAAgD,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;IAC7K,yBAAyB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,kDAAkD,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;IAC5L,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gDAAgD,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,+BAA+B,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;CACxK,CAAC"}
1
+ {"version":3,"file":"capacity.js","sourceRoot":"","sources":["../../commands/capacity.ts"],"names":[],"mappings":"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"}
@@ -302,6 +302,26 @@ export declare const COMMAND_GROUPS: {
302
302
  description: string;
303
303
  body: string[];
304
304
  };
305
+ 'capacity.notifications': {
306
+ method: "GET";
307
+ path: string;
308
+ auth: "apiKey";
309
+ description: string;
310
+ };
311
+ 'capacity.notifications-update': {
312
+ method: "PATCH";
313
+ path: string;
314
+ auth: "apiKey";
315
+ description: string;
316
+ body: string[];
317
+ };
318
+ 'capacity.notification-state': {
319
+ method: "GET";
320
+ path: string;
321
+ auth: "apiKey";
322
+ description: string;
323
+ queryParams: string[];
324
+ };
305
325
  'capacity.pause': {
306
326
  method: "POST";
307
327
  path: string;
@@ -1,9 +1,9 @@
1
1
  export const projectCommands = {
2
2
  'projects.all': { method: 'GET', path: '/api/admin/projects', auth: 'apiKey', description: 'List all projects', queryParams: ['status', 'clientId'] },
3
3
  'projects.list': { method: 'GET', path: '/api/admin/clients/:id/projects', auth: 'apiKey', description: 'List client projects' },
4
- 'projects.create': { method: 'POST', path: '/api/admin/clients/:id/projects', auth: 'apiKey', description: 'Create a project', body: ['name', 'description', 'startDate', 'targetDate', 'valueEur', 'externalRef', 'metricsConfig', 'itemsConfig'] },
4
+ 'projects.create': { method: 'POST', path: '/api/admin/clients/:id/projects', auth: 'apiKey', description: 'Create a project', body: ['name', 'status', 'visibility', 'description', 'startDate', 'targetDate', 'valueEur', 'externalRef', 'metricsConfig', 'itemsConfig'] },
5
5
  'projects.get': { method: 'GET', path: '/api/admin/projects/:id', auth: 'apiKey', description: 'Get a project' },
6
- 'projects.update': { method: 'PATCH', path: '/api/admin/projects/:id', auth: 'apiKey', description: 'Update a project', body: ['name', 'status', 'description', 'startDate', 'targetDate', 'valueEur', 'externalRef', 'metricsConfig', 'itemsConfig'] },
6
+ 'projects.update': { method: 'PATCH', path: '/api/admin/projects/:id', auth: 'apiKey', description: 'Update a project', body: ['name', 'status', 'visibility', 'description', 'startDate', 'targetDate', 'valueEur', 'externalRef', 'metricsConfig', 'itemsConfig'] },
7
7
  'projects.delete': { method: 'DELETE', path: '/api/admin/projects/:id', auth: 'apiKey', description: 'Delete a project' },
8
8
  'projects.docs-invoices': { method: 'GET', path: '/api/admin/projects/:id/docs/invoices', auth: 'apiKey', description: 'List project invoices' },
9
9
  'projects.docs-documents': { method: 'GET', path: '/api/admin/projects/:id/docs/documents', auth: 'apiKey', description: 'List project documents' },
@@ -1 +1 @@
1
- {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../commands/projects.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE;IACrJ,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;IAChI,iBAAiB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE;IACpP,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;IAChH,iBAAiB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE;IACvP,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;IACzH,wBAAwB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,uCAAuC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;IAChJ,yBAAyB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,wCAAwC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;IACnJ,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;IACzG,gBAAgB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE;IACxH,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE;IAC/G,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvH,mBAAmB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;CACxF,CAAC"}
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../commands/projects.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE;IACrJ,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;IAChI,iBAAiB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE;IAC5Q,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;IAChH,iBAAiB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE;IACrQ,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;IACzH,wBAAwB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,uCAAuC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;IAChJ,yBAAyB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,wCAAwC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;IACnJ,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;IACzG,gBAAgB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE;IACxH,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE;IAC/G,iBAAiB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvH,mBAAmB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;CACxF,CAAC"}
@@ -271,6 +271,41 @@ function interpolatePath(template, id) {
271
271
  return template.replace(':id', id);
272
272
  }
273
273
 
274
+ const HELP_ENUMS = {
275
+ priority: 'low|normal|high|urgent',
276
+ submittedBy: 'client|admin|va',
277
+ phase: 'current|next|future',
278
+ billableStatus: 'included|goodwill|non_billable|out_of_scope|separate_quote',
279
+ approvalStatus: 'pending|approved|rejected',
280
+ visibleToClient: 'true|false',
281
+ countsAgainstCapacity: 'true|false',
282
+ author: 'kingsley|va|system',
283
+ unitType: 'hours|credits',
284
+ periodType: 'monthly|weekly',
285
+ resetBehavior: 'reset|rollover|no_rollover',
286
+ notifyAtWarning: 'true|false',
287
+ notifyAtCap: 'true|false',
288
+ notifyOverCap: 'true|false',
289
+ notifyOnReset: 'true|false',
290
+ notifyClient: 'true|false',
291
+ notifyAdmin: 'true|false',
292
+ };
293
+
294
+ function helpFlag(commandKey, field) {
295
+ let hint = HELP_ENUMS[field];
296
+ if (field === 'visibility') {
297
+ if (commandKey.startsWith('projects.')) hint = 'client_visible|internal_only';
298
+ else if (commandKey.startsWith('capacity.')) hint = 'internal_only|client_visible_summary|client_visible_detail';
299
+ else hint = 'client|internal';
300
+ }
301
+ if (field === 'status') {
302
+ if (commandKey.startsWith('projects.')) hint = 'discovery|in_progress|review|delivered|maintenance|on_hold';
303
+ else if (commandKey.startsWith('capacity.')) hint = 'active|paused|ended';
304
+ else if (commandKey.startsWith('tasks.')) hint = 'open|in_progress|done|blocked';
305
+ }
306
+ return hint ? `--${field} ${hint}` : `--${field}`;
307
+ }
308
+
274
309
  // ── Output Formatting ───────────────────────────────────────────
275
310
 
276
311
  function formatOutput(data, commandKey) {
@@ -328,7 +363,10 @@ function formatOutput(data, commandKey) {
328
363
  console.log(` Portal: /c/${c.portalSlug}?token=${c.portalToken}`);
329
364
  if (data.projects?.length > 0) {
330
365
  console.log(`\n Projects (${data.projects.length}):`);
331
- for (const p of data.projects) console.log(` • ${p.name} [${p.status}] [${p.id}]`);
366
+ for (const p of data.projects) {
367
+ const visibility = p.visibility ? ` [${p.visibility}]` : '';
368
+ console.log(` • ${p.name} [${p.status}]${visibility} [${p.id}]`);
369
+ }
332
370
  }
333
371
  return;
334
372
  }
@@ -337,6 +375,7 @@ function formatOutput(data, commandKey) {
337
375
  const p = data.project;
338
376
  console.log(`\n${p.name} [${p.status}]`);
339
377
  console.log(` ID: ${p.id}`);
378
+ if (p.visibility) console.log(` Visibility: ${p.visibility}`);
340
379
  if (p.description) console.log(` ${p.description}`);
341
380
  if (p.startDate) console.log(` Start: ${p.startDate} | Target: ${p.targetDate || '—'}`);
342
381
  if (p.valueEur) console.log(` Value: €${p.valueEur}`);
@@ -483,7 +522,8 @@ function formatOutput(data, commandKey) {
483
522
  console.log('\nProjects:');
484
523
  for (const p of items) {
485
524
  const client = p.clientName ? ` (${p.clientName})` : '';
486
- console.log(` • ${p.name}${client} [${p.status}] [${p.id}]`);
525
+ const visibility = p.visibility ? ` [${p.visibility}]` : '';
526
+ console.log(` • ${p.name}${client} [${p.status}]${visibility} [${p.id}]`);
487
527
  }
488
528
  } else if (commandKey === 'onboarding.list') {
489
529
  console.log('\nPending Submissions:');
@@ -546,7 +586,8 @@ function formatOutput(data, commandKey) {
546
586
  }
547
587
  if (data.project) {
548
588
  const p = data.project;
549
- console.log(`Project: ${p.name} [${p.status}] [${p.id}]`);
589
+ const visibility = p.visibility ? ` [${p.visibility}]` : '';
590
+ console.log(`Project: ${p.name} [${p.status}]${visibility} [${p.id}]`);
550
591
  if (p.valueEur) console.log(` Value: €${p.valueEur}`);
551
592
  return;
552
593
  }
@@ -614,12 +655,12 @@ if (!resource || resource === 'help' || resource === '--help') {
614
655
  for (const [key, cmd] of Object.entries(COMMANDS)) {
615
656
  const [res, act] = key.includes('.') ? key.split('.') : [key, ''];
616
657
  if (!grouped[res]) grouped[res] = [];
617
- grouped[res].push({ action: act, desc: (cmd.description || cmd.desc), body: cmd.body });
658
+ grouped[res].push({ key, action: act, desc: (cmd.description || cmd.desc), body: cmd.body });
618
659
  }
619
660
  for (const [res, cmds] of Object.entries(grouped)) {
620
661
  console.log(`\n ${res}:`);
621
662
  for (const c of cmds) {
622
- const bodyHint = c.body ? ` [${c.body.map(b => '--' + b).join(' ')}]` : '';
663
+ const bodyHint = c.body ? ` [${c.body.map(b => helpFlag(c.key, b)).join(' ')}]` : '';
623
664
  console.log(` ${c.action || '(default)'} — ${c.desc}${bodyHint}`);
624
665
  }
625
666
  }
@@ -736,7 +777,8 @@ if (commandKey === 'search') {
736
777
  if (data.projects.length > 0) {
737
778
  console.log('\nProjects:');
738
779
  data.projects.forEach((p) => {
739
- console.log(` • ${p.name} (${p.clientName}) [${p.status}] [${p.id}]`);
780
+ const visibility = p.visibility ? ` [${p.visibility}]` : '';
781
+ console.log(` • ${p.name} (${p.clientName}) [${p.status}]${visibility} [${p.id}]`);
740
782
  });
741
783
  } else {
742
784
  console.log('\nProjects: (none)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klevar/portal-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "First-class npm CLI for the Klevar Client Management Portal",
5
5
  "type": "module",
6
6
  "bin": {