@@ -20,6 +20,7 @@ import type {
2020 NodeFilter
2121} from './types.js' ;
2222import { GraphError , NotFoundError } from './errors.js' ;
23+ import type { CodeGraphApi , ImpactAnalysisResult , ArchitectureSummary } from './graph.js' ;
2324
2425// Traversal limits from EML (reused for consistency)
2526export const MAX_TRAVERSE_DEPTH = 12 ;
@@ -40,21 +41,7 @@ interface CacheEntry {
4041 accessedAt : number ;
4142}
4243
43- export interface ImpactAnalysisResult {
44- affectedNodes : CodeNode [ ] ;
45- affectedFiles : Set < string > ;
46- depth : number ;
47- confidence : number ;
48- }
49-
50- export interface ArchitectureSummary {
51- entryPoints : CodeNode [ ] ;
52- modules : Map < string , CodeNode [ ] > ;
53- keyAbstractions : CodeNode [ ] ;
54- packageStructure : Record < string , number > ;
55- }
56-
57- export class StorageBackedGraph {
44+ export class StorageBackedGraph implements CodeGraphApi {
5845 private readonly storage : StorageProvider ;
5946 private readonly maxCacheEntries : number ;
6047 private readonly nodeCache = new Map < string , CachedNode > ( ) ;
@@ -606,9 +593,106 @@ export class StorageBackedGraph {
606593 }
607594 }
608595
609- // Invalidate cache entries (will be used by write methods in Phase 12)
610- // private invalidateCache(): void {
611- // this.nodeCache.clear();
612- // this.queryCache.clear();
613- // }
596+ // ============================================================================
597+ // WRITE METHODS (Phase 12)
598+ // ============================================================================
599+
600+ async addNode ( node : CodeNode ) : Promise < void > {
601+ // Write to storage
602+ this . storage . upsertNodes ( [ node ] ) ;
603+
604+ // Cache the new node
605+ this . cacheNode ( node ) ;
606+
607+ // Invalidate related queries that might be affected
608+ this . invalidateQueryCache ( ) ;
609+ }
610+
611+ async addEdge ( edge : GraphEdge ) : Promise < void > {
612+ // Write to storage
613+ this . storage . upsertEdges ( [ edge ] ) ;
614+
615+ // Invalidate cache since edge affects traversal results
616+ this . invalidateQueryCache ( ) ;
617+ }
618+
619+ async bulkLoad ( nodes : CodeNode [ ] , edges : GraphEdge [ ] ) : Promise < void > {
620+ // Write all nodes and edges to storage
621+ if ( nodes . length > 0 ) {
622+ this . storage . upsertNodes ( nodes ) ;
623+
624+ // Cache hot nodes
625+ for ( const node of nodes ) {
626+ this . cacheNode ( node ) ;
627+ }
628+ }
629+
630+ if ( edges . length > 0 ) {
631+ this . storage . upsertEdges ( edges ) ;
632+ }
633+
634+ // Clear all caches to ensure consistency
635+ this . invalidateAllCaches ( ) ;
636+ }
637+
638+ async removeNode ( nodeId : string ) : Promise < void > {
639+ // Remove from storage
640+ this . storage . deleteNode ( nodeId ) ;
641+ this . storage . deleteEdgesForNode ( nodeId ) ;
642+
643+ // Remove from caches
644+ this . nodeCache . delete ( nodeId ) ;
645+ this . invalidateQueryCache ( ) ;
646+ }
647+
648+ async removeNodesInFile ( filePath : string ) : Promise < void > {
649+ // Remove from storage
650+ this . storage . deleteNodesInFile ( filePath ) ;
651+
652+ // Clear caches (could be more surgical but this is safe)
653+ this . invalidateAllCaches ( ) ;
654+ }
655+
656+ // ============================================================================
657+ // CACHE INVALIDATION
658+ // ============================================================================
659+
660+ private invalidateQueryCache ( ) : void {
661+ this . queryCache . clear ( ) ;
662+ }
663+
664+ private invalidateAllCaches ( ) : void {
665+ this . nodeCache . clear ( ) ;
666+ this . queryCache . clear ( ) ;
667+ }
668+
669+ // ============================================================================
670+ // ADDITIONAL METHODS FOR API COMPATIBILITY
671+ // ============================================================================
672+
673+ getAllEdges ( ) : GraphEdge [ ] {
674+ return this . storage . getEdges ( ) ;
675+ }
676+
677+ serialize ( ) : string {
678+ // For StorageBackedGraph, serialization is the SQLite database itself
679+ // Return a marker indicating this is storage-backed
680+ return JSON . stringify ( {
681+ type : 'StorageBackedGraph' ,
682+ timestamp : new Date ( ) . toISOString ( ) ,
683+ nodeCount : this . storage . countNodes ( ) ,
684+ edgeCount : this . storage . getStats ( ) . edgeCount ,
685+ } ) ;
686+ }
687+
688+ async deserialize ( _data : string ) : Promise < void > {
689+ // For StorageBackedGraph, deserialization is not needed since data lives in SQLite
690+ // This is a no-op for compatibility
691+ console . log ( 'StorageBackedGraph.deserialize called - no action needed (data in SQLite)' ) ;
692+ }
693+
694+ clear ( ) : void {
695+ // Clear caches but don't clear the storage (that would delete all data!)
696+ this . invalidateAllCaches ( ) ;
697+ }
614698}
0 commit comments