@klevar/portal-cli 0.1.0 → 0.1.2

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
@@ -7,7 +7,7 @@ First-class npm CLI for the Klevar Client Management Portal.
7
7
  Run without installing:
8
8
 
9
9
  ```bash
10
- npx klevar-portal help
10
+ npx @klevar/portal-cli help
11
11
  ```
12
12
 
13
13
  Install globally for repeated use:
@@ -34,33 +34,33 @@ Do not paste API keys, portal tokens, or production secrets into chat logs, issu
34
34
  ## Command Examples
35
35
 
36
36
  ```bash
37
- npx klevar-portal health
38
- npx klevar-portal tenant info
39
- npx klevar-portal clients list
40
- npx klevar-portal clients create --name "Stefan" --email "stefan@example.de" --platform direct
41
- npx klevar-portal projects create <clientId> --name "Idealo" --externalRef "idealo:ksh.de"
42
- npx klevar-portal metrics push --external_ref "idealo:ksh.de" --source_ref "run:33" --snapshot_date "2026-04-12" --metrics '{"score":88}'
43
- npx klevar-portal portal me --portal-token "<client-token>"
37
+ npx @klevar/portal-cli health
38
+ npx @klevar/portal-cli tenant info
39
+ npx @klevar/portal-cli clients list
40
+ npx @klevar/portal-cli clients create --name "Stefan" --email "stefan@example.de" --platform direct
41
+ npx @klevar/portal-cli projects create <clientId> --name "Idealo" --externalRef "idealo:ksh.de"
42
+ npx @klevar/portal-cli metrics push --external_ref "idealo:ksh.de" --source_ref "run:33" --snapshot_date "2026-04-12" --metrics '{"score":88}'
43
+ npx @klevar/portal-cli portal me --portal-token "<client-token>"
44
44
  ```
45
45
 
46
46
  ## Brain Usage
47
47
 
48
- Brain usage should prefer the published `npx klevar-portal` entrypoint.
48
+ Brain usage should prefer the published `npx @klevar/portal-cli` entrypoint.
49
49
 
50
50
  Brain agents should call:
51
51
 
52
52
  ```bash
53
- npx klevar-portal <resource> <action> [id] [--key value]
53
+ npx @klevar/portal-cli <resource> <action> [id] [--key value]
54
54
  ```
55
55
 
56
56
  The local compatibility wrapper remains available for old automation after a build:
57
57
 
58
58
  ```bash
59
59
  npm run cli:build
60
- node tools/client.js clients list
60
+ klevar-portal clients list
61
61
  ```
62
62
 
63
- New automation should use `npx klevar-portal`.
63
+ New automation should use `npx @klevar/portal-cli`.
64
64
 
65
65
  ## Auth Modes
66
66
 
@@ -0,0 +1,94 @@
1
+ export declare const capacityCommands: {
2
+ 'capacity.list': {
3
+ method: "GET";
4
+ path: string;
5
+ auth: "apiKey";
6
+ description: string;
7
+ };
8
+ 'capacity.get': {
9
+ method: "GET";
10
+ path: string;
11
+ auth: "apiKey";
12
+ description: string;
13
+ };
14
+ 'capacity.create': {
15
+ method: "POST";
16
+ path: string;
17
+ auth: "apiKey";
18
+ description: string;
19
+ body: string[];
20
+ };
21
+ 'capacity.update': {
22
+ method: "PATCH";
23
+ path: string;
24
+ auth: "apiKey";
25
+ description: string;
26
+ body: string[];
27
+ };
28
+ 'capacity.pause': {
29
+ method: "POST";
30
+ path: string;
31
+ auth: "apiKey";
32
+ description: string;
33
+ };
34
+ 'capacity.resume': {
35
+ method: "POST";
36
+ path: string;
37
+ auth: "apiKey";
38
+ description: string;
39
+ };
40
+ 'capacity.end': {
41
+ method: "POST";
42
+ path: string;
43
+ auth: "apiKey";
44
+ description: string;
45
+ };
46
+ 'capacity.delete': {
47
+ method: "DELETE";
48
+ path: string;
49
+ auth: "apiKey";
50
+ description: string;
51
+ };
52
+ 'capacity.summary': {
53
+ method: "GET";
54
+ path: string;
55
+ auth: "apiKey";
56
+ description: string;
57
+ queryParams: string[];
58
+ };
59
+ 'capacity.client-summary': {
60
+ method: "GET";
61
+ path: string;
62
+ auth: "apiKey";
63
+ description: string;
64
+ queryParams: string[];
65
+ };
66
+ 'capacity.budget-summary': {
67
+ method: "GET";
68
+ path: string;
69
+ auth: "apiKey";
70
+ description: string;
71
+ queryParams: string[];
72
+ };
73
+ 'capacity.report': {
74
+ method: "GET";
75
+ path: string;
76
+ auth: "apiKey";
77
+ description: string;
78
+ queryParams: string[];
79
+ };
80
+ 'capacity.portal-summary': {
81
+ method: "GET";
82
+ path: string;
83
+ auth: "portalToken";
84
+ description: string;
85
+ queryParams: string[];
86
+ };
87
+ 'capacity.portal-usage': {
88
+ method: "GET";
89
+ path: string;
90
+ auth: "portalToken";
91
+ description: string;
92
+ queryParams: string[];
93
+ };
94
+ };
@@ -0,0 +1,23 @@
1
+ const budgetBody = [
2
+ 'name', 'description', 'clientId', 'laneKey', 'unitType', 'customUnitLabel',
3
+ 'periodType', 'periodStartDay', 'startDate', 'endDate', 'capacityAmount',
4
+ 'warningThresholdPct', 'hardCap', 'allowOverage', 'overagePolicy',
5
+ 'resetBehavior', 'rolloverCapAmount', 'visibility', 'status', 'sortOrder',
6
+ ];
7
+ export const capacityCommands = {
8
+ 'capacity.list': { method: 'GET', path: '/api/admin/projects/:projectId/capacity-budgets', auth: 'apiKey', description: 'List project capacity budgets' },
9
+ 'capacity.get': { method: 'GET', path: '/api/admin/capacity-budgets/:id', auth: 'apiKey', description: 'Get a capacity budget' },
10
+ 'capacity.create': { method: 'POST', path: '/api/admin/projects/:projectId/capacity-budgets', auth: 'apiKey', description: 'Create a capacity budget', body: budgetBody },
11
+ 'capacity.update': { method: 'PATCH', path: '/api/admin/capacity-budgets/:id', auth: 'apiKey', description: 'Update a capacity budget', body: budgetBody },
12
+ 'capacity.pause': { method: 'POST', path: '/api/admin/capacity-budgets/:id/pause', auth: 'apiKey', description: 'Pause a capacity budget' },
13
+ 'capacity.resume': { method: 'POST', path: '/api/admin/capacity-budgets/:id/resume', auth: 'apiKey', description: 'Resume a capacity budget' },
14
+ 'capacity.end': { method: 'POST', path: '/api/admin/capacity-budgets/:id/end', auth: 'apiKey', description: 'End a capacity budget' },
15
+ 'capacity.delete': { method: 'DELETE', path: '/api/admin/capacity-budgets/:id', auth: 'apiKey', description: 'Delete a capacity budget' },
16
+ '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'] },
18
+ 'capacity.budget-summary': { method: 'GET', path: '/api/admin/capacity-budgets/:id/summary', auth: 'apiKey', description: 'Budget capacity summary', queryParams: ['period'] },
19
+ 'capacity.report': { method: 'GET', path: '/api/admin/projects/:projectId/capacity-report', auth: 'apiKey', description: 'Project capacity report', queryParams: ['period'] },
20
+ 'capacity.portal-summary': { method: 'GET', path: '/api/portal/projects/:projectId/capacity-summary', auth: 'portalToken', description: 'Portal capacity summary', queryParams: ['period'] },
21
+ 'capacity.portal-usage': { method: 'GET', path: '/api/portal/projects/:projectId/capacity-usage', auth: 'portalToken', description: 'Portal visible capacity usage', queryParams: ['period'] },
22
+ };
23
+ //# sourceMappingURL=capacity.js.map
@@ -0,0 +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,0BAA0B,EAAE,IAAI,EAAE,UAAU,EAAE;IACzK,iBAAiB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE,IAAI,EAAE,UAAU,EAAE;IAC1J,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"}
@@ -275,6 +275,148 @@ export declare const COMMAND_GROUPS: {
275
275
  body: string[];
276
276
  };
277
277
  };
278
+ capacity: {
279
+ 'capacity.list': {
280
+ method: "GET";
281
+ path: string;
282
+ auth: "apiKey";
283
+ description: string;
284
+ };
285
+ 'capacity.get': {
286
+ method: "GET";
287
+ path: string;
288
+ auth: "apiKey";
289
+ description: string;
290
+ };
291
+ 'capacity.create': {
292
+ method: "POST";
293
+ path: string;
294
+ auth: "apiKey";
295
+ description: string;
296
+ body: string[];
297
+ };
298
+ 'capacity.update': {
299
+ method: "PATCH";
300
+ path: string;
301
+ auth: "apiKey";
302
+ description: string;
303
+ body: string[];
304
+ };
305
+ 'capacity.pause': {
306
+ method: "POST";
307
+ path: string;
308
+ auth: "apiKey";
309
+ description: string;
310
+ };
311
+ 'capacity.resume': {
312
+ method: "POST";
313
+ path: string;
314
+ auth: "apiKey";
315
+ description: string;
316
+ };
317
+ 'capacity.end': {
318
+ method: "POST";
319
+ path: string;
320
+ auth: "apiKey";
321
+ description: string;
322
+ };
323
+ 'capacity.delete': {
324
+ method: "DELETE";
325
+ path: string;
326
+ auth: "apiKey";
327
+ description: string;
328
+ };
329
+ 'capacity.summary': {
330
+ method: "GET";
331
+ path: string;
332
+ auth: "apiKey";
333
+ description: string;
334
+ queryParams: string[];
335
+ };
336
+ 'capacity.client-summary': {
337
+ method: "GET";
338
+ path: string;
339
+ auth: "apiKey";
340
+ description: string;
341
+ queryParams: string[];
342
+ };
343
+ 'capacity.budget-summary': {
344
+ method: "GET";
345
+ path: string;
346
+ auth: "apiKey";
347
+ description: string;
348
+ queryParams: string[];
349
+ };
350
+ 'capacity.report': {
351
+ method: "GET";
352
+ path: string;
353
+ auth: "apiKey";
354
+ description: string;
355
+ queryParams: string[];
356
+ };
357
+ 'capacity.portal-summary': {
358
+ method: "GET";
359
+ path: string;
360
+ auth: "portalToken";
361
+ description: string;
362
+ queryParams: string[];
363
+ };
364
+ 'capacity.portal-usage': {
365
+ method: "GET";
366
+ path: string;
367
+ auth: "portalToken";
368
+ description: string;
369
+ queryParams: string[];
370
+ };
371
+ };
372
+ usage: {
373
+ 'usage.list': {
374
+ method: "GET";
375
+ path: string;
376
+ auth: "apiKey";
377
+ description: string;
378
+ queryParams: string[];
379
+ };
380
+ 'usage.record': {
381
+ method: "POST";
382
+ path: string;
383
+ auth: "apiKey";
384
+ description: string;
385
+ body: string[];
386
+ };
387
+ 'usage.manual': {
388
+ method: "POST";
389
+ path: string;
390
+ auth: "apiKey";
391
+ description: string;
392
+ body: string[];
393
+ };
394
+ 'usage.update': {
395
+ method: "PATCH";
396
+ path: string;
397
+ auth: "apiKey";
398
+ description: string;
399
+ body: string[];
400
+ };
401
+ 'usage.approve': {
402
+ method: "POST";
403
+ path: string;
404
+ auth: "apiKey";
405
+ description: string;
406
+ };
407
+ 'usage.reject': {
408
+ method: "POST";
409
+ path: string;
410
+ auth: "apiKey";
411
+ description: string;
412
+ };
413
+ 'usage.delete': {
414
+ method: "DELETE";
415
+ path: string;
416
+ auth: "apiKey";
417
+ description: string;
418
+ };
419
+ };
278
420
  updates: {
279
421
  'updates.list': {
280
422
  method: "GET";
@@ -1,17 +1,21 @@
1
1
  import { clientCommands } from './clients.js';
2
2
  import { docsCommands } from './docs.js';
3
+ import { capacityCommands } from './capacity.js';
3
4
  import { metricCommands } from './metrics.js';
4
5
  import { onboardingCommands } from './onboarding.js';
5
6
  import { portalCommands } from './portal.js';
6
7
  import { projectCommands } from './projects.js';
7
8
  import { systemCommands } from './system.js';
8
9
  import { taskCommands } from './tasks.js';
10
+ import { usageCommands } from './usage.js';
9
11
  import { updateCommands } from './updates.js';
10
12
  export const COMMAND_GROUPS = {
11
13
  system: systemCommands,
12
14
  clients: clientCommands,
13
15
  projects: projectCommands,
14
16
  tasks: taskCommands,
17
+ capacity: capacityCommands,
18
+ usage: usageCommands,
15
19
  updates: updateCommands,
16
20
  onboarding: onboardingCommands,
17
21
  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,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,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,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,kBAAkB;IAC9B,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,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,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,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,8 +1,8 @@
1
1
  export const taskCommands = {
2
2
  'tasks.all': { method: 'GET', path: '/api/admin/tasks', auth: 'apiKey', description: 'List all tasks', queryParams: ['status', 'phase', 'priority', 'clientId'] },
3
3
  'tasks.list': { method: 'GET', path: '/api/admin/projects/:id/tasks', auth: 'apiKey', description: 'List project tasks' },
4
- 'tasks.create': { method: 'POST', path: '/api/admin/projects/:id/tasks', auth: 'apiKey', description: 'Create a task', body: ['title', 'description', 'priority', 'submittedBy', 'phase'] },
4
+ 'tasks.create': { method: 'POST', path: '/api/admin/projects/:id/tasks', auth: 'apiKey', description: 'Create a task', body: ['title', 'description', 'priority', 'submittedBy', 'phase', 'laneKey', 'capacityBudgetId', 'estimatedUnits', 'actualUnits', 'countsAgainstCapacity', 'outOfScopeReason'] },
5
5
  'tasks.delete': { method: 'DELETE', path: '/api/admin/tasks/:id', auth: 'apiKey', description: 'Delete a task' },
6
- 'tasks.update': { method: 'PATCH', path: '/api/admin/tasks/:id', auth: 'apiKey', description: 'Update a task', body: ['status', 'priority', 'description', 'phase'] },
6
+ 'tasks.update': { method: 'PATCH', path: '/api/admin/tasks/:id', auth: 'apiKey', description: 'Update a task', body: ['status', 'priority', 'description', 'phase', 'laneKey', 'capacityBudgetId', 'estimatedUnits', 'actualUnits', 'countsAgainstCapacity', 'outOfScopeReason'] },
7
7
  };
8
8
  //# sourceMappingURL=tasks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../commands/tasks.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE;IACjK,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACzH,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;IAC3L,cAAc,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;IAChH,cAAc,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;CAC/I,CAAC"}
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../commands/tasks.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE;IACjK,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACzH,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,uBAAuB,EAAE,kBAAkB,CAAC,EAAE;IACxS,cAAc,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;IAChH,cAAc,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,uBAAuB,EAAE,kBAAkB,CAAC,EAAE;CAC5P,CAAC"}
@@ -0,0 +1,48 @@
1
+ export declare const usageCommands: {
2
+ 'usage.list': {
3
+ method: "GET";
4
+ path: string;
5
+ auth: "apiKey";
6
+ description: string;
7
+ queryParams: string[];
8
+ };
9
+ 'usage.record': {
10
+ method: "POST";
11
+ path: string;
12
+ auth: "apiKey";
13
+ description: string;
14
+ body: string[];
15
+ };
16
+ 'usage.manual': {
17
+ method: "POST";
18
+ path: string;
19
+ auth: "apiKey";
20
+ description: string;
21
+ body: string[];
22
+ };
23
+ 'usage.update': {
24
+ method: "PATCH";
25
+ path: string;
26
+ auth: "apiKey";
27
+ description: string;
28
+ body: string[];
29
+ };
30
+ 'usage.approve': {
31
+ method: "POST";
32
+ path: string;
33
+ auth: "apiKey";
34
+ description: string;
35
+ };
36
+ 'usage.reject': {
37
+ method: "POST";
38
+ path: string;
39
+ auth: "apiKey";
40
+ description: string;
41
+ };
42
+ 'usage.delete': {
43
+ method: "DELETE";
44
+ path: string;
45
+ auth: "apiKey";
46
+ description: string;
47
+ };
48
+ };
@@ -0,0 +1,15 @@
1
+ const usageBody = [
2
+ 'budgetId', 'clientId', 'projectId', 'updateId', 'units', 'usageDate',
3
+ 'title', 'notes', 'internalNotes', 'billableStatus', 'approvalStatus',
4
+ 'visibleToClient', 'countsAgainstCapacity',
5
+ ];
6
+ export const usageCommands = {
7
+ 'usage.list': { method: 'GET', path: '/api/admin/projects/:projectId/capacity-usage', auth: 'apiKey', description: 'List project capacity usage', queryParams: ['period'] },
8
+ 'usage.record': { method: 'POST', path: '/api/admin/tasks/:taskId/capacity-usage', auth: 'apiKey', description: 'Record usage for a task', body: usageBody },
9
+ 'usage.manual': { method: 'POST', path: '/api/admin/capacity-usage', auth: 'apiKey', description: 'Record manual usage', body: usageBody },
10
+ 'usage.update': { method: 'PATCH', path: '/api/admin/capacity-usage/:id', auth: 'apiKey', description: 'Update usage', body: usageBody },
11
+ 'usage.approve': { method: 'POST', path: '/api/admin/capacity-usage/:id/approve', auth: 'apiKey', description: 'Approve pending usage' },
12
+ 'usage.reject': { method: 'POST', path: '/api/admin/capacity-usage/:id/reject', auth: 'apiKey', description: 'Reject pending usage' },
13
+ 'usage.delete': { method: 'DELETE', path: '/api/admin/capacity-usage/:id', auth: 'apiKey', description: 'Delete usage' },
14
+ };
15
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../commands/usage.ts"],"names":[],"mappings":"AAEA,MAAM,SAAS,GAAG;IAChB,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW;IACrE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB;IACrE,iBAAiB,EAAE,uBAAuB;CAC3C,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,+CAA+C,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6BAA6B,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE;IAC3K,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,yCAAyC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE,IAAI,EAAE,SAAS,EAAE;IAC5J,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qBAAqB,EAAE,IAAI,EAAE,SAAS,EAAE;IAC1I,cAAc,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE;IACxI,eAAe,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;IACxI,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,sCAAsC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;IACrI,cAAc,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;CAClG,CAAC"}
@@ -5,13 +5,15 @@
5
5
  * Uses X-API-Key header for authentication.
6
6
  *
7
7
  * Usage:
8
- * node client.js <resource> <action> [id] [--key value ...]
8
+ * klevar-portal <resource> <action> [id] [--key value ...]
9
+ * npx @klevar/portal-cli <resource> <action> [id] [--key value ...]
9
10
  *
10
11
  * Resources: clients, projects, tasks, updates, onboarding, dashboard, token
11
12
  *
12
13
  * Config:
13
14
  * PORTAL_API_KEY — API key (env var or ~/.klevar/portal.env)
14
- * PORTAL_URL — API base URL (default: http://localhost:3000)
15
+ * PORTAL_API_URL - API base URL (default: http://127.0.0.1:3100)
16
+ * PORTAL_TOKEN - client portal token for portal commands
15
17
  *
16
18
  * To add a new API endpoint:
17
19
  * 1. Add an entry to COMMANDS: 'resource.action': { method, path, body? }
@@ -579,7 +581,8 @@ let [,, resource, action, ...rest] = process.argv;
579
581
 
580
582
  if (!resource || resource === 'help' || resource === '--help') {
581
583
  console.log('Klevar Client Portal CLI\n');
582
- console.log('Usage: node client.js <resource> <action> [id] [--key value ...]\n');
584
+ console.log('Usage: klevar-portal <resource> <action> [id] [--key value ...]');
585
+ console.log(' npx @klevar/portal-cli <resource> <action> [id] [--key value ...]\n');
583
586
  console.log('Commands:');
584
587
  const grouped = {};
585
588
  for (const [key, cmd] of Object.entries(COMMANDS)) {
@@ -594,7 +597,7 @@ if (!resource || resource === 'help' || resource === '--help') {
594
597
  console.log(` ${c.action || '(default)'} — ${c.desc}${bodyHint}`);
595
598
  }
596
599
  }
597
- console.log(`\nConfig: PORTAL_API_KEY, PORTAL_URL (or ~/.klevar/portal.env)`);
600
+ console.log(`\nConfig: PORTAL_API_URL, PORTAL_API_KEY, PORTAL_TOKEN (or ~/.klevar/portal.env)`);
598
601
  console.log(`Target: ${BASE_URL}`);
599
602
  process.exit(0);
600
603
  }
@@ -619,7 +622,7 @@ if (!cmd && COMMANDS[resource]) {
619
622
 
620
623
  if (!cmd) {
621
624
  console.error(`Unknown command: ${commandKey}`);
622
- console.error(`Run 'node client.js help' for available commands.`);
625
+ console.error(`Run 'klevar-portal help' for available commands.`);
623
626
  process.exit(1);
624
627
  }
625
628
 
@@ -674,6 +677,8 @@ if (cmd.fixedBody) {
674
677
  if (typeof val === 'string' && (val.startsWith('{') || val.startsWith('['))) {
675
678
  try { val = JSON.parse(val); } catch { /* keep as string */ }
676
679
  }
680
+ if (val === 'true') val = true;
681
+ if (val === 'false') val = false;
677
682
  body[key] = val;
678
683
  }
679
684
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klevar/portal-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "First-class npm CLI for the Klevar Client Management Portal",
5
5
  "type": "module",
6
6
  "bin": {