feat(files): add markdown entity read/write
This commit is contained in:
parent
dd27e8caba
commit
57bb572bf5
38
src/core/files.ts
Normal file
38
src/core/files.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'fs';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
import YAML from 'yaml';
|
||||||
|
|
||||||
|
export interface EntityFile {
|
||||||
|
frontmatter: Record<string, unknown>;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeEntity(filePath: string, frontmatter: Record<string, unknown>, body: string): void {
|
||||||
|
mkdirSync(dirname(filePath), { recursive: true });
|
||||||
|
const yaml = YAML.stringify(frontmatter, { lineWidth: 0 });
|
||||||
|
const content = `---\n${yaml}---\n${body}\n`;
|
||||||
|
writeFileSync(filePath, content, 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readEntity(filePath: string): EntityFile {
|
||||||
|
if (!existsSync(filePath)) {
|
||||||
|
throw new Error(`File not found: ${filePath}`);
|
||||||
|
}
|
||||||
|
const content = readFileSync(filePath, 'utf-8');
|
||||||
|
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(`Invalid entity format in ${filePath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const frontmatter = YAML.parse(match[1]) as Record<string, unknown>;
|
||||||
|
const body = match[2].trim();
|
||||||
|
|
||||||
|
return { frontmatter, body };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listEntities(dir: string): string[] {
|
||||||
|
if (!existsSync(dir)) return [];
|
||||||
|
const entries = readdirSync(dir);
|
||||||
|
return entries.filter((f) => f.endsWith('.md')).map((f) => join(dir, f));
|
||||||
|
}
|
||||||
30
tests/files.test.ts
Normal file
30
tests/files.test.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||||
|
import { mkdtempSync, rmSync, existsSync } from 'fs';
|
||||||
|
import { tmpdir } from 'os';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { writeEntity, readEntity } from '../src/core/files.js';
|
||||||
|
|
||||||
|
describe('files', () => {
|
||||||
|
let cwd: string;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cwd = mkdtempSync(join(tmpdir(), 'agenthub-'));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
rmSync(cwd, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('writes and reads a markdown entity', () => {
|
||||||
|
const filePath = join(cwd, 'test.md');
|
||||||
|
const frontmatter = { id: 'TSK-0001', title: 'Test' };
|
||||||
|
const body = '# Test\n\nHello';
|
||||||
|
|
||||||
|
writeEntity(filePath, frontmatter, body);
|
||||||
|
const result = readEntity(filePath);
|
||||||
|
|
||||||
|
expect(result.frontmatter.id).toBe('TSK-0001');
|
||||||
|
expect(result.body.trim()).toBe('# Test\n\nHello');
|
||||||
|
expect(existsSync(filePath)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user