import { Pool } from 'pg'; export interface CategoryNode { id: number; name: string; path: string; } export class CategoryRepository { // Inject the database connection pool constructor(private db: Pool) { } /** * Finds all descendants of a given path (including the path itself). * Uses the ltree operator <@ (is-descendant-of). */ async findAllDescendants(parentPath: string): Promise { const query = ` SELECT id, name, path FROM categories WHERE path <@ $1::ltree ORDER BY path ASC; `; const result = await this.db.query(query, [parentPath]); return result.rows; } /** * Finds only the direct children of a given path. * Uses lquery pattern matching (parent.*) and matches the exact next depth level. */ async findDirectChildren(parentPath: string): Promise { const query = ` SELECT id, name, path FROM categories WHERE path ~ $1::lquery AND nlevel(path) = nlevel($2::ltree) + 1; `; const values = [`${parentPath}.*`, parentPath]; const result = await this.db.query(query, values); return result.rows; } /** * Finds all ancestors of a path (useful for breadcrumbs). * Uses the ltree operator @> (is-ancestor-of). */ async findAncestors(childPath: string): Promise { const query = ` SELECT id, name, path FROM categories WHERE path @> $1::ltree ORDER BY nlevel(path) ASC; `; const result = await this.db.query(query, [childPath]); return result.rows; } }