feat: add topic hierarchy APIs
This commit is contained in:
@@ -16,7 +16,7 @@ afterEach(async () => {
|
||||
});
|
||||
|
||||
describe('initializeSchema', () => {
|
||||
it('creates the topics, facts, and fact_topics tables', async () => {
|
||||
it('creates the topics, facts, fact_topics, and topic_relations tables', async () => {
|
||||
const connection = await createDatabase({ client: 'sqlite', filename: ':memory:' });
|
||||
openConnections.push(connection.destroy);
|
||||
|
||||
@@ -34,6 +34,7 @@ describe('initializeSchema', () => {
|
||||
expect(tableNames).toContain('topics');
|
||||
expect(tableNames).toContain('facts');
|
||||
expect(tableNames).toContain('fact_topics');
|
||||
expect(tableNames).toContain('topic_relations');
|
||||
});
|
||||
|
||||
it('creates the expected columns for each table', async () => {
|
||||
@@ -45,6 +46,7 @@ describe('initializeSchema', () => {
|
||||
const topicsColumns = await sql<{ name: string }>`PRAGMA table_info(topics)`.execute(connection.db);
|
||||
const factsColumns = await sql<{ name: string }>`PRAGMA table_info(facts)`.execute(connection.db);
|
||||
const factTopicsColumns = await sql<{ name: string }>`PRAGMA table_info(fact_topics)`.execute(connection.db);
|
||||
const topicRelationsColumns = await sql<{ name: string }>`PRAGMA table_info(topic_relations)`.execute(connection.db);
|
||||
|
||||
expect(topicsColumns.rows.map((row) => row.name)).toEqual([
|
||||
'id',
|
||||
@@ -76,6 +78,13 @@ describe('initializeSchema', () => {
|
||||
'position',
|
||||
'created_at',
|
||||
]);
|
||||
|
||||
expect(topicRelationsColumns.rows.map((row) => row.name)).toEqual([
|
||||
'parent_topic_id',
|
||||
'child_topic_id',
|
||||
'relation',
|
||||
'created_at',
|
||||
]);
|
||||
});
|
||||
|
||||
it('is idempotent when called more than once', async () => {
|
||||
|
||||
@@ -19,6 +19,16 @@ async function seedMemoryGraph(db: IdentityDB): Promise<void> {
|
||||
{ name: 'programming language', category: 'concept', granularity: 'abstract', role: 'classification' },
|
||||
],
|
||||
});
|
||||
|
||||
await db.linkTopics({
|
||||
parentName: 'software technology',
|
||||
childName: 'programming language',
|
||||
});
|
||||
|
||||
await db.linkTopics({
|
||||
parentName: 'programming language',
|
||||
childName: 'TypeScript',
|
||||
});
|
||||
}
|
||||
|
||||
describe('IdentityDB queries', () => {
|
||||
@@ -60,6 +70,7 @@ describe('IdentityDB queries', () => {
|
||||
'2025',
|
||||
'I',
|
||||
'programming language',
|
||||
'software technology',
|
||||
'TypeScript',
|
||||
]);
|
||||
expect('facts' in topics[0]!).toBe(false);
|
||||
@@ -81,4 +92,25 @@ describe('IdentityDB queries', () => {
|
||||
expect(facts).toHaveLength(1);
|
||||
expect(facts[0]?.statement).toBe('I have worked with TypeScript since 2025.');
|
||||
});
|
||||
|
||||
it('lists direct child topics for a parent topic', async () => {
|
||||
const children = await db.getTopicChildren('programming language');
|
||||
|
||||
expect(children.map((topic) => topic.name)).toEqual(['TypeScript']);
|
||||
});
|
||||
|
||||
it('lists direct parent topics for a child topic', async () => {
|
||||
const parents = await db.getTopicParents('TypeScript');
|
||||
|
||||
expect(parents.map((topic) => topic.name)).toEqual(['programming language']);
|
||||
});
|
||||
|
||||
it('returns lineage from nearest parent outward', async () => {
|
||||
const lineage = await db.getTopicLineage('TypeScript');
|
||||
|
||||
expect(lineage.map((topic) => topic.name)).toEqual([
|
||||
'programming language',
|
||||
'software technology',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user