From 433f403fe243592cc7a092ef2d6b2c88dca09256 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 ceff9f51b..cf7f0a57c 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 aa85196ce..d2159e3be 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 53a4dab75..4949c33f2 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 efe94286d..201198624 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 669c61139..02fd4b6b6 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; }