From 06fc3e3f068da55e5553333008dd75e8d390aa63 Mon Sep 17 00:00:00 2001 From: jreakin Date: Mon, 23 Mar 2026 02:53:17 -0500 Subject: [PATCH] fix(web): 18 multi-language CSV tables, RFC 4180 escaping, schema sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Generate CSVs for Struct, Enum, Macro, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module, Namespace, Union, Typedef (were defined in schema but silently dropped during CSV generation — non-JS/TS repos lost all nodes) - Escape community keywords array in CSV to prevent comma breakage - Add Section to NodeLabel type, NODE_COLORS, NODE_SIZES - Add 7 missing REL_TYPES: HAS_METHOD, HAS_PROPERTY, OVERRIDES, ACCESSES, INHERITS, USES, DECORATES - RFC 4180 doubled-quote regex for relation CSV parsing Co-Authored-By: Claude Opus 4.6 (1M context) --- gitnexus-web/src/core/graph/types.ts | 3 +- gitnexus-web/src/core/lbug/csv-generator.ts | 43 ++++++++++++++++++++- gitnexus-web/src/core/lbug/schema.ts | 2 +- gitnexus-web/src/lib/constants.ts | 2 + gitnexus-web/src/types/lbug-wasm.d.ts | 5 +-- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/gitnexus-web/src/core/graph/types.ts b/gitnexus-web/src/core/graph/types.ts index ceff9f51bf..cf7f0a57c1 100644 --- a/gitnexus-web/src/core/graph/types.ts +++ b/gitnexus-web/src/core/graph/types.ts @@ -15,7 +15,8 @@ export type NodeLabel = | 'Type' | 'CodeElement' | 'Community' - | 'Process'; + | 'Process' + | 'Section'; export type NodeProperties = { diff --git a/gitnexus-web/src/core/lbug/csv-generator.ts b/gitnexus-web/src/core/lbug/csv-generator.ts index aa85196ceb..d2159e3be7 100644 --- a/gitnexus-web/src/core/lbug/csv-generator.ts +++ b/gitnexus-web/src/core/lbug/csv-generator.ts @@ -202,6 +202,35 @@ const generateCodeElementCSV = ( return rows.join('\n'); }; +/** + * Generate CSV for multi-language code element nodes (Struct, Enum, Macro, etc.) + * These do NOT have isExported column. + * Headers: id,name,filePath,startLine,endLine,content + */ +const generateMultiLangCSV = ( + nodes: GraphNode[], + label: NodeLabel, + fileContents: Map +): string => { + const headers = ['id', 'name', 'filePath', 'startLine', 'endLine', 'content']; + 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), + ].join(',')); + } + + return rows.join('\n'); +}; + /** * Generate CSV for Community nodes (from Leiden algorithm) * Headers: id,label,heuristicLabel,keywords,description,enrichedBy,cohesion,symbolCount @@ -221,7 +250,7 @@ const generateCommunityCSV = (nodes: GraphNode[]): string => { escapeCSVField(node.id), escapeCSVField(node.properties.name || ''), // label is stored in name escapeCSVField(node.properties.heuristicLabel || ''), - keywordsStr, // Array format for LadybugDB + escapeCSVField(keywordsStr), // Array format for LadybugDB, needs CSV escaping for commas escapeCSVField((node.properties as any).description || ''), escapeCSVField((node.properties as any).enrichedBy || 'heuristic'), escapeCSVNumber(node.properties.cohesion, 0), @@ -312,7 +341,17 @@ export const generateAllCSVs = ( nodeCSVs.set('CodeElement', generateCodeElementCSV(nodes, 'CodeElement', fileContents)); nodeCSVs.set('Community', generateCommunityCSV(nodes)); nodeCSVs.set('Process', generateProcessCSV(nodes)); - + + // Generate CSVs for remaining multi-language tables (no isExported column) + const handledTables = new Set([ + 'File', 'Folder', 'Function', 'Class', 'Interface', 'Method', 'CodeElement', 'Community', 'Process', + ]); + for (const table of NODE_TABLES) { + if (!handledTables.has(table)) { + nodeCSVs.set(table, generateMultiLangCSV(nodes, table as NodeLabel, fileContents)); + } + } + // Generate single relation CSV const relCSV = generateRelationCSV(graph); diff --git a/gitnexus-web/src/core/lbug/schema.ts b/gitnexus-web/src/core/lbug/schema.ts index 53a4dab750..4949c33f2f 100644 --- a/gitnexus-web/src/core/lbug/schema.ts +++ b/gitnexus-web/src/core/lbug/schema.ts @@ -26,7 +26,7 @@ export type NodeTableName = typeof NODE_TABLES[number]; export const REL_TABLE_NAME = 'CodeRelation'; // Valid relation types -export const REL_TYPES = ['CONTAINS', 'DEFINES', 'IMPORTS', 'CALLS', 'EXTENDS', 'IMPLEMENTS', 'MEMBER_OF', 'STEP_IN_PROCESS'] as const; +export const REL_TYPES = ['CONTAINS', 'DEFINES', 'IMPORTS', 'CALLS', 'EXTENDS', 'IMPLEMENTS', 'MEMBER_OF', 'STEP_IN_PROCESS', 'HAS_METHOD', 'HAS_PROPERTY', 'OVERRIDES', 'ACCESSES', 'INHERITS', 'USES', 'DECORATES'] as const; export type RelType = typeof REL_TYPES[number]; // ============================================================================ diff --git a/gitnexus-web/src/lib/constants.ts b/gitnexus-web/src/lib/constants.ts index efe94286d2..2011986243 100644 --- a/gitnexus-web/src/lib/constants.ts +++ b/gitnexus-web/src/lib/constants.ts @@ -19,6 +19,7 @@ export const NODE_COLORS: Record = { CodeElement: '#64748b', // Slate - muted Community: '#818cf8', // Indigo light - cluster indicator Process: '#f43f5e', // Rose - execution flow indicator + Section: '#60a5fa', // Blue light - structural section }; // Node sizes by type - clear visual hierarchy with dramatic size differences @@ -41,6 +42,7 @@ export const NODE_SIZES: Record = { CodeElement: 2, // Generic small Community: 0, // Hidden by default - metadata node Process: 0, // Hidden by default - metadata node + Section: 8, // Structural section - similar to Folder }; // Community color palette for cluster-based coloring diff --git a/gitnexus-web/src/types/lbug-wasm.d.ts b/gitnexus-web/src/types/lbug-wasm.d.ts index 669c61139b..02fd4b6b64 100644 --- a/gitnexus-web/src/types/lbug-wasm.d.ts +++ b/gitnexus-web/src/types/lbug-wasm.d.ts @@ -12,9 +12,8 @@ declare module '@ladybugdb/wasm-core' { close(): Promise; } export interface QueryResult { - getAll?(): Promise; - getAllRows?(): Promise; - getAllObjects?(): Promise; + getAll(): Promise; + getAllRows(): Promise; hasNext(): Promise; getNext(): Promise; }