tenbo-dashboard 0.10.0 → 0.10.1
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/package.json +1 -1
- package/scripts/bin-output.test.ts +15 -0
- package/scripts/items.test.ts +20 -0
- package/scripts/items.ts +6 -3
- package/scripts/next-id.test.ts +1 -1
- package/scripts/next-id.ts +1 -5
- package/src/api/lib/itemProjection.ts +3 -0
- package/tsconfig.json +1 -1
package/package.json
CHANGED
|
@@ -56,4 +56,19 @@ describe('bin output', () => {
|
|
|
56
56
|
{ id: 'ed-001', title: 'Large Output', status: 'done' },
|
|
57
57
|
]);
|
|
58
58
|
});
|
|
59
|
+
|
|
60
|
+
it('prints items help without running the query', () => {
|
|
61
|
+
const bin = path.resolve('bin/tenbo-dashboard.mjs');
|
|
62
|
+
const result = spawnSync(process.execPath, [bin, 'items', '--help'], {
|
|
63
|
+
cwd: dir,
|
|
64
|
+
encoding: 'utf8',
|
|
65
|
+
maxBuffer: 1024 * 1024,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(result.status).toBe(0);
|
|
69
|
+
expect(result.stderr).toBe('');
|
|
70
|
+
expect(result.stdout).toContain('Usage: tenbo-dashboard items');
|
|
71
|
+
expect(result.stdout).toContain('--fields <a,b>');
|
|
72
|
+
expect(result.stdout).not.toContain('ed-001');
|
|
73
|
+
});
|
|
59
74
|
});
|
package/scripts/items.test.ts
CHANGED
|
@@ -82,6 +82,26 @@ describe('items CLI', () => {
|
|
|
82
82
|
]);
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
it('includes goal_ref in selected compact fields', () => {
|
|
86
|
+
writeFileSync(path.join(dir, '.tenbo/scopes/editor/roadmap.yaml'), [
|
|
87
|
+
'items:',
|
|
88
|
+
' - id: ed-001',
|
|
89
|
+
' title: First',
|
|
90
|
+
' layer: app',
|
|
91
|
+
' status: next',
|
|
92
|
+
' description: first item',
|
|
93
|
+
' goal_ref: [g1, g2]',
|
|
94
|
+
'',
|
|
95
|
+
].join('\n'));
|
|
96
|
+
|
|
97
|
+
const result = runItemsCli(dir, ['--fields', 'id,title,goal_ref', '--json']);
|
|
98
|
+
|
|
99
|
+
expect(result.exitCode).toBe(0);
|
|
100
|
+
expect(JSON.parse(result.stdout).items).toEqual([
|
|
101
|
+
{ id: 'ed-001', title: 'First', goal_ref: ['g1', 'g2'] },
|
|
102
|
+
]);
|
|
103
|
+
});
|
|
104
|
+
|
|
85
105
|
it('returns compact summaries without changing full JSON by default', () => {
|
|
86
106
|
const summary = runItemsCli(dir, ['--status', 'next', '--summary', '--json']);
|
|
87
107
|
const full = runItemsCli(dir, ['--status', 'next', '--json']);
|
package/scripts/items.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { listItems, type ListItemFilters } from '../src/api/lib/roadmapStore';
|
|
2
2
|
import { parseItemFields, projectItem, summarizeItem } from '../src/api/lib/itemProjection';
|
|
3
3
|
import { hasFlag, readOption } from './cliArgs';
|
|
4
|
-
import { handleCliError, isMain, misuse, repoRootFromCwd, runMain, serialize, type CliResult } from './cliResult';
|
|
4
|
+
import { handleCliError, isMain, misuse, ok, repoRootFromCwd, runMain, serialize, type CliResult } from './cliResult';
|
|
5
5
|
|
|
6
6
|
const STATUSES = new Set(['now', 'next', 'later', 'done', 'dropped']);
|
|
7
|
+
const USAGE = `Usage: tenbo-dashboard items [--status <status[,status]>] [--verification <status>] [--goal <goal>] [--type <type>] [--priority <p0|p1|p2|p3>] [--layer <id>] [--fields <a,b>] [--summary] [--json]
|
|
8
|
+
`;
|
|
7
9
|
|
|
8
10
|
function readStatusFilter(value: string | undefined): ListItemFilters['status'] {
|
|
9
11
|
if (!value) return undefined;
|
|
@@ -49,7 +51,8 @@ export function runItemsCli(repoRoot: string, args: string[]): CliResult {
|
|
|
49
51
|
if (isMain(import.meta.url)) {
|
|
50
52
|
const args = process.argv.slice(2);
|
|
51
53
|
if (args.includes('--help')) {
|
|
52
|
-
runMain(
|
|
54
|
+
runMain(ok(USAGE));
|
|
55
|
+
} else {
|
|
56
|
+
runMain(runItemsCli(repoRootFromCwd(), args));
|
|
53
57
|
}
|
|
54
|
-
runMain(runItemsCli(repoRootFromCwd(), args));
|
|
55
58
|
}
|
package/scripts/next-id.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync,
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, readdirSync, utimesSync } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { spawnSync } from 'node:child_process';
|
package/scripts/next-id.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* decoration so callers can capture it via `$(...)`. Errors go to stderr
|
|
28
28
|
* and the process exits non-zero.
|
|
29
29
|
*/
|
|
30
|
-
import { readFileSync, existsSync, mkdirSync,
|
|
30
|
+
import { readFileSync, existsSync, mkdirSync, statSync, unlinkSync, openSync, closeSync, writeSync } from 'node:fs';
|
|
31
31
|
import path from 'node:path';
|
|
32
32
|
import { parse as parseYaml } from 'yaml';
|
|
33
33
|
import { findRepoRoot } from '../src/api/lib/repoRoot';
|
|
@@ -41,10 +41,6 @@ interface WorkspaceScope {
|
|
|
41
41
|
path?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
interface RoadmapFile {
|
|
45
|
-
items?: Array<{ id?: string }>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
44
|
/** Find which roadmap.yaml files contain ids for this prefix. */
|
|
49
45
|
export function resolveRoadmapPaths(repoRoot: string, prefix: string): string[] {
|
|
50
46
|
const tenbo = path.join(repoRoot, '.tenbo');
|
|
@@ -10,6 +10,7 @@ export interface ItemSummaryRecord {
|
|
|
10
10
|
layers?: string[];
|
|
11
11
|
type?: Item['type'];
|
|
12
12
|
priority?: Priority;
|
|
13
|
+
goal_ref?: Item['goal_ref'];
|
|
13
14
|
verification?: VerificationStatus;
|
|
14
15
|
risk_count?: number;
|
|
15
16
|
done_when_count?: number;
|
|
@@ -25,6 +26,7 @@ export const ITEM_FIELD_NAMES = [
|
|
|
25
26
|
'layers',
|
|
26
27
|
'type',
|
|
27
28
|
'priority',
|
|
29
|
+
'goal_ref',
|
|
28
30
|
'verification',
|
|
29
31
|
'risk_count',
|
|
30
32
|
'done_when_count',
|
|
@@ -60,6 +62,7 @@ export function summarizeItem(entry: LocatedItem): ItemSummaryRecord {
|
|
|
60
62
|
...(item.layers ? { layers: item.layers } : {}),
|
|
61
63
|
...(item.type ? { type: item.type } : {}),
|
|
62
64
|
...(item.priority ? { priority: item.priority } : {}),
|
|
65
|
+
...(item.goal_ref ? { goal_ref: item.goal_ref } : {}),
|
|
63
66
|
...(item.verification?.status ? { verification: item.verification.status } : {}),
|
|
64
67
|
...(item.risks ? { risk_count: item.risks.length } : {}),
|
|
65
68
|
...(item.done_when ? { done_when_count: item.done_when.length } : {}),
|
package/tsconfig.json
CHANGED