feat: attach project context to read issues
This commit is contained in:
parent
0b127b5404
commit
fb3f6c3e55
2 changed files with 22 additions and 5 deletions
|
|
@ -3,11 +3,14 @@ import path from 'node:path';
|
||||||
|
|
||||||
import { parseIssuesJsonl } from './parser';
|
import { parseIssuesJsonl } from './parser';
|
||||||
import { canonicalizeWindowsPath } from './pathing';
|
import { canonicalizeWindowsPath } from './pathing';
|
||||||
import type { BeadIssue } from './types';
|
import { buildProjectContext } from './project-context';
|
||||||
|
import type { BeadIssueWithProject, ProjectSource } from './types';
|
||||||
|
|
||||||
export interface ReadIssuesOptions {
|
export interface ReadIssuesOptions {
|
||||||
projectRoot?: string;
|
projectRoot?: string;
|
||||||
includeTombstones?: boolean;
|
includeTombstones?: boolean;
|
||||||
|
projectSource?: ProjectSource;
|
||||||
|
projectAddedAt?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveIssuesJsonlPathCandidates(projectRoot: string = process.cwd()): string[] {
|
export function resolveIssuesJsonlPathCandidates(projectRoot: string = process.cwd()): string[] {
|
||||||
|
|
@ -21,15 +24,23 @@ export function resolveIssuesJsonlPath(projectRoot: string = process.cwd()): str
|
||||||
return resolveIssuesJsonlPathCandidates(projectRoot)[0];
|
return resolveIssuesJsonlPathCandidates(projectRoot)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readIssuesFromDisk(options: ReadIssuesOptions = {}): Promise<BeadIssue[]> {
|
export async function readIssuesFromDisk(options: ReadIssuesOptions = {}): Promise<BeadIssueWithProject[]> {
|
||||||
const candidates = resolveIssuesJsonlPathCandidates(options.projectRoot);
|
const projectRoot = options.projectRoot ?? process.cwd();
|
||||||
|
const candidates = resolveIssuesJsonlPathCandidates(projectRoot);
|
||||||
|
const project = buildProjectContext(projectRoot, {
|
||||||
|
source: options.projectSource ?? 'local',
|
||||||
|
addedAt: options.projectAddedAt ?? null,
|
||||||
|
});
|
||||||
|
|
||||||
for (const issuesPath of candidates) {
|
for (const issuesPath of candidates) {
|
||||||
try {
|
try {
|
||||||
const jsonl = await fs.readFile(issuesPath, 'utf8');
|
const jsonl = await fs.readFile(issuesPath, 'utf8');
|
||||||
return parseIssuesJsonl(jsonl, {
|
return parseIssuesJsonl(jsonl, {
|
||||||
includeTombstones: options.includeTombstones ?? false,
|
includeTombstones: options.includeTombstones ?? false,
|
||||||
});
|
}).map((issue) => ({
|
||||||
|
...issue,
|
||||||
|
project,
|
||||||
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import os from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
import { readIssuesFromDisk, resolveIssuesJsonlPath, resolveIssuesJsonlPathCandidates } from '../../src/lib/read-issues';
|
import { readIssuesFromDisk, resolveIssuesJsonlPath, resolveIssuesJsonlPathCandidates } from '../../src/lib/read-issues';
|
||||||
import { sameWindowsPath } from '../../src/lib/pathing';
|
import { canonicalizeWindowsPath, sameWindowsPath, toDisplayPath, windowsPathKey } from '../../src/lib/pathing';
|
||||||
|
|
||||||
test('resolveIssuesJsonlPath appends .beads/issues.jsonl using windows-safe pathing', () => {
|
test('resolveIssuesJsonlPath appends .beads/issues.jsonl using windows-safe pathing', () => {
|
||||||
const resolved = resolveIssuesJsonlPath('C:/Repo/Project');
|
const resolved = resolveIssuesJsonlPath('C:/Repo/Project');
|
||||||
|
|
@ -38,6 +38,12 @@ test('readIssuesFromDisk parses JSONL issues from disk', async () => {
|
||||||
assert.equal(issues.length, 1);
|
assert.equal(issues.length, 1);
|
||||||
assert.equal(issues[0].id, 'bb-1');
|
assert.equal(issues[0].id, 'bb-1');
|
||||||
assert.equal(issues[0].priority, 0);
|
assert.equal(issues[0].priority, 0);
|
||||||
|
assert.equal(issues[0].project.root, canonicalizeWindowsPath(root));
|
||||||
|
assert.equal(issues[0].project.key, windowsPathKey(root));
|
||||||
|
assert.equal(issues[0].project.displayPath, toDisplayPath(root));
|
||||||
|
assert.equal(issues[0].project.name, path.basename(canonicalizeWindowsPath(root)));
|
||||||
|
assert.equal(issues[0].project.source, 'local');
|
||||||
|
assert.equal(issues[0].project.addedAt, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('readIssuesFromDisk returns empty list when issues file does not exist', async () => {
|
test('readIssuesFromDisk returns empty list when issues file does not exist', async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue