diff --git a/gitnexus/src/core/kuzu/csv-generator.ts b/gitnexus/src/core/kuzu/csv-generator.ts index 266309570..735ebab02 100644 --- a/gitnexus/src/core/kuzu/csv-generator.ts +++ b/gitnexus/src/core/kuzu/csv-generator.ts @@ -180,16 +180,16 @@ const generateFolderCSV = (nodes: GraphNode[]): string => { /** * Generate CSV for code element nodes (Function, Class, Interface, Method, CodeElement) - * Headers: id,name,filePath,startLine,endLine,isExported,content + * Headers: id,name,filePath,startLine,endLine,isExported,content,description */ const generateCodeElementCSV = ( nodes: GraphNode[], label: NodeLabel, fileContents: Map ): string => { - const headers = ['id', 'name', 'filePath', 'startLine', 'endLine', 'isExported', 'content']; + const headers = ['id', 'name', 'filePath', 'startLine', 'endLine', 'isExported', 'content', 'description']; const rows: string[] = [headers.join(',')]; - + for (const node of nodes) { if (node.label !== label) continue; const content = extractContent(node, fileContents); @@ -201,9 +201,10 @@ const generateCodeElementCSV = ( escapeCSVNumber(node.properties.endLine, -1), node.properties.isExported ? 'true' : 'false', escapeCSVField(content), + escapeCSVField((node.properties as any).description || ''), ].join(',')); } - + return rows.join('\n'); }; @@ -267,6 +268,35 @@ const generateProcessCSV = (nodes: GraphNode[]): string => { return rows.join('\n'); }; +/** + * Generate CSV for multi-language node tables (Struct, Enum, Trait, Property, etc.) + * These use CODE_ELEMENT_BASE schema: id,name,filePath,startLine,endLine,content,description + */ +const generateMultiLangNodeCSV = ( + nodes: GraphNode[], + label: string, + fileContents: Map +): string => { + const headers = ['id', 'name', 'filePath', 'startLine', 'endLine', 'content', 'description']; + const rows: string[] = [headers.join(',')]; + + for (const node of nodes) { + if (node.label !== label) continue; + const content = extractContent(node, fileContents); + rows.push([ + escapeCSVField(node.id), + escapeCSVField(node.properties.name || ''), + escapeCSVField(node.properties.filePath || ''), + escapeCSVNumber(node.properties.startLine, -1), + escapeCSVNumber(node.properties.endLine, -1), + escapeCSVField(content), + escapeCSVField((node.properties as any).description || ''), + ].join(',')); + } + + return rows.join('\n'); +}; + /** * Generate CSV for the single CodeRelation table * Headers: from,to,type,confidence,reason @@ -317,7 +347,17 @@ export const generateAllCSVs = ( nodeCSVs.set('CodeElement', generateCodeElementCSV(nodes, 'CodeElement', fileContents)); nodeCSVs.set('Community', generateCommunityCSV(nodes)); nodeCSVs.set('Process', generateProcessCSV(nodes)); - + + // Multi-language node types (CODE_ELEMENT_BASE schema: id,name,filePath,startLine,endLine,content,description) + const multiLangTypes = [ + 'Struct', 'Enum', 'Macro', 'Typedef', 'Union', 'Namespace', 'Trait', 'Impl', + 'TypeAlias', 'Const', 'Static', 'Property', 'Record', 'Delegate', 'Annotation', + 'Constructor', 'Template', 'Module', + ] as const; + for (const mlType of multiLangTypes) { + nodeCSVs.set(mlType, generateMultiLangNodeCSV(nodes, mlType, fileContents)); + } + // Generate single relation CSV const relCSV = generateRelationCSV(graph); diff --git a/gitnexus/src/core/kuzu/kuzu-adapter.ts b/gitnexus/src/core/kuzu/kuzu-adapter.ts index 9988b56ed..09e52a265 100644 --- a/gitnexus/src/core/kuzu/kuzu-adapter.ts +++ b/gitnexus/src/core/kuzu/kuzu-adapter.ts @@ -282,8 +282,12 @@ const getCopyQuery = (table: NodeTableName, filePath: string): string => { if (table === 'Process') { return `COPY ${t}(id, label, heuristicLabel, processType, stepCount, communities, entryPointId, terminalId) FROM "${filePath}" ${COPY_CSV_OPTS}`; } - // Code element tables (Function, Class, Interface, Method, CodeElement, and multi-language) - return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content) FROM "${filePath}" ${COPY_CSV_OPTS}`; + // Multi-language code element tables (CODE_ELEMENT_BASE: no isExported, has description) + if (BACKTICK_TABLES.has(table)) { + return `COPY ${t}(id, name, filePath, startLine, endLine, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`; + } + // Core code element tables (Function, Class, Interface, Method, CodeElement) + return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`; }; /** @@ -320,7 +324,8 @@ export const insertNodeToKuzu = async ( query = `CREATE (n:Folder {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}})`; } else { // Function, Class, Method, Interface, etc. - standard code element schema - query = `CREATE (n:${label} {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, startLine: ${properties.startLine || 0}, endLine: ${properties.endLine || 0}, content: ${escapeValue(properties.content || '')}})`; + const descStr = properties.description ? `, description: ${escapeValue(properties.description)}` : ''; + query = `CREATE (n:${label} {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, startLine: ${properties.startLine || 0}, endLine: ${properties.endLine || 0}, content: ${escapeValue(properties.content || '')}${descStr}})`; } // Use per-query connection if dbPath provided (avoids lock conflicts) @@ -385,7 +390,8 @@ export const batchInsertNodesToKuzu = async ( } else if (label === 'Folder') { query = `MERGE (n:Folder {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}`; } else { - query = `MERGE (n:${label} {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.startLine = ${properties.startLine || 0}, n.endLine = ${properties.endLine || 0}, n.content = ${escapeValue(properties.content || '')}`; + const descPart = properties.description ? `, n.description = ${escapeValue(properties.description)}` : ''; + query = `MERGE (n:${label} {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.startLine = ${properties.startLine || 0}, n.endLine = ${properties.endLine || 0}, n.content = ${escapeValue(properties.content || '')}${descPart}`; } await tempConn.query(query); diff --git a/gitnexus/src/core/kuzu/schema.ts b/gitnexus/src/core/kuzu/schema.ts index c0f3b394a..a50b52338 100644 --- a/gitnexus/src/core/kuzu/schema.ts +++ b/gitnexus/src/core/kuzu/schema.ts @@ -64,6 +64,7 @@ CREATE NODE TABLE Function ( endLine INT64, isExported BOOLEAN, content STRING, + description STRING, PRIMARY KEY (id) )`; @@ -76,6 +77,7 @@ CREATE NODE TABLE Class ( endLine INT64, isExported BOOLEAN, content STRING, + description STRING, PRIMARY KEY (id) )`; @@ -88,6 +90,7 @@ CREATE NODE TABLE Interface ( endLine INT64, isExported BOOLEAN, content STRING, + description STRING, PRIMARY KEY (id) )`; @@ -100,6 +103,7 @@ CREATE NODE TABLE Method ( endLine INT64, isExported BOOLEAN, content STRING, + description STRING, PRIMARY KEY (id) )`; @@ -112,6 +116,7 @@ CREATE NODE TABLE CodeElement ( endLine INT64, isExported BOOLEAN, content STRING, + description STRING, PRIMARY KEY (id) )`; @@ -154,6 +159,7 @@ CREATE NODE TABLE Process ( // ============================================================================ // Generic code element with startLine/endLine for C, C++, Rust, Go, Java, C# +// description: optional metadata (e.g. Eloquent $fillable fields, relationship targets) const CODE_ELEMENT_BASE = (name: string) => ` CREATE NODE TABLE \`${name}\` ( id STRING, @@ -162,6 +168,7 @@ CREATE NODE TABLE \`${name}\` ( startLine INT64, endLine INT64, content STRING, + description STRING, PRIMARY KEY (id) )`;