@@ -30,7 +30,6 @@ export class StreamingJsonReplacer {
3030 private onErrorCallback : ( error : Error ) => void
3131 private itemsProcessed : number = 0
3232 private successfullyParsedItems : ReplacementItem [ ] = [ ]
33- private logFilePath : string
3433
3534 constructor (
3635 initialContent : string ,
@@ -39,212 +38,100 @@ export class StreamingJsonReplacer {
3938 ) {
4039 // Initialize log file path
4140 const timestamp = new Date ( ) . toISOString ( ) . replace ( / [: .] / g, "-" )
42- this . logFilePath = path . join ( os . homedir ( ) , "Documents" , `streaming-json-replacer-debug-${ timestamp } .log` )
43-
44- // Initialize log file
45- this . log ( "StreamingJsonReplacer Debug Log Started" , "INFO" )
46- this . log ( "Timestamp: " + new Date ( ) . toISOString ( ) , "INFO" )
47- this . log ( "Constructor called with initial content length: " + initialContent . length , "INFO" )
48- this . log ( "Initial content preview: " + initialContent . substring ( 0 , 200 ) + "..." , "INFO" )
4941
5042 this . currentFileContent = initialContent
5143 this . onContentUpdated = onContentUpdatedCallback
5244 this . onErrorCallback = onErrorCallback
5345
54- this . log ( "Initializing JSONParser with paths: ['$.*']" , "INFO" )
5546 this . parser = new JSONParser ( { paths : [ "$.*" ] } )
5647
5748 this . parser . onValue = ( parsedElementInfo : ParsedElementInfo ) => {
58- this . log ( "onValue callback triggered" )
59- this . log ( "parsedElementInfo: " + JSON . stringify ( parsedElementInfo , null , 2 ) )
60-
6149 const { value } = parsedElementInfo // Destructure to get value, which might be undefined
62- this . log ( "Extracted value: " + JSON . stringify ( value ) )
63- this . log ( "Value type: " + typeof value )
6450
6551 // This callback is triggered for each item matched by '$.replacements.*'
6652 if ( value && typeof value === "object" && "old_string" in value && "new_string" in value ) {
67- this . log ( "Found valid replacement item structure" )
6853 const item = value as ReplacementItem // Value here is confirmed to be an object
69- this . log ( "Replacement item: " + JSON . stringify ( item , null , 2 ) )
70-
7154 if ( typeof item . old_string === "string" && typeof item . new_string === "string" ) {
72- this . log ( "Item has valid string types for old_string and new_string" )
73- this . log ( "old_string length: " + item . old_string . length )
74- this . log ( "new_string length: " + item . new_string . length )
75- this . log (
76- "old_string preview: " +
77- ( item . old_string . substring ( 0 , 100 ) + ( item . old_string . length > 100 ? "..." : "" ) ) ,
78- )
79- this . log (
80- "new_string preview: " +
81- ( item . new_string . substring ( 0 , 100 ) + ( item . new_string . length > 100 ? "..." : "" ) ) ,
82- )
83-
8455 this . successfullyParsedItems . push ( item ) // Store the structurally valid item
85- this . log ( "Added item to successfullyParsedItems. Total count: " + this . successfullyParsedItems . length )
8656
8757 if ( this . currentFileContent . includes ( item . old_string ) ) {
88- this . log ( "old_string found in current file content - proceeding with replacement" )
89-
9058 // Calculate the change location before making the replacement
9159 const changeLocation = this . calculateChangeLocation ( item . old_string , item . new_string )
92- this . log ( "Calculated change location: " + JSON . stringify ( changeLocation ) )
9360
9461 const beforeLength = this . currentFileContent . length
9562 this . currentFileContent = this . currentFileContent . replace ( item . old_string , item . new_string )
9663 const afterLength = this . currentFileContent . length
97- this . log ( "Content length before replacement: " + beforeLength )
98- this . log ( "Content length after replacement: " + afterLength )
99- this . log ( "Length difference: " + ( afterLength - beforeLength ) )
10064
10165 this . itemsProcessed ++
102- this . log ( "Incremented itemsProcessed to: " + this . itemsProcessed )
10366
10467 // Notify that an item has been processed. The `isFinalItem` argument here is tricky
10568 // as we don't know from the parser alone if this is the *absolute* last item
10669 // until the stream ends. The caller (Task.ts) will manage the final update.
10770 // For now, we'll pass `false` and let Task.ts handle the final diff view update.
108- this . log ( "Calling onContentUpdated callback" )
10971 this . onContentUpdated ( this . currentFileContent , false , changeLocation )
110- this . log ( "onContentUpdated callback completed" )
11172 } else {
112- this . log ( "old_string NOT found in current file content - generating error" , "ERROR" )
113- this . log ( "Current file content length: " + this . currentFileContent . length )
114- this . log ( "Current file content preview: " + this . currentFileContent . substring ( 0 , 200 ) + "..." )
115-
11673 const snippet = item . old_string . length > 50 ? item . old_string . substring ( 0 , 47 ) + "..." : item . old_string
11774 const error = new Error ( `Streaming Replacement failed: 'old_string' not found. Snippet: "${ snippet } "` )
118- this . log ( "Calling onErrorCallback with error: " + error . message , "ERROR" )
11975 this . onErrorCallback ( error ) // Call our own error callback
12076 }
12177 } else {
122- this . log (
123- "Invalid string types - old_string type: " +
124- typeof item . old_string +
125- ", new_string type: " +
126- typeof item . new_string ,
127- "ERROR" ,
128- )
12978 const error = new Error ( `Invalid item structure in replacements stream: ${ JSON . stringify ( item ) } ` )
130- this . log ( "Calling onErrorCallback with error: " + error . message , "ERROR" )
13179 this . onErrorCallback ( error ) // Call our own error callback
13280 }
133- } else if ( value && ( Array . isArray ( value ) || ( typeof value === "object" && "replacements" in value ) ) ) {
134- // This might be the 'replacements' array itself or the root object.
135- // The `paths: ['$.replacements.*']` should mean we only get items.
136- // If we get here, it's likely the root object if paths wasn't specific enough or if it's an empty replacements array.
137- this . log ( "Streaming parser emitted container: " + JSON . stringify ( value ) )
138- this . log (
139- "Container type - isArray: " +
140- Array . isArray ( value ) +
141- ", hasReplacements: " +
142- ( typeof value === "object" && "replacements" in value ) ,
143- )
144- } else {
145- // Value is not a ReplacementItem or a known container, could be an issue with the JSON structure or path.
146- // If `paths` is correct, this path should ideally not be hit often for valid streams.
147- this . log ( "Streaming parser emitted unexpected value: " + JSON . stringify ( value ) , "WARN" )
148- this . log ( "Unexpected value type: " + typeof value , "WARN" )
149- this . log ( "Has old_string: " + ( value && typeof value === "object" && "old_string" in value ) , "WARN" )
150- this . log ( "Has new_string: " + ( value && typeof value === "object" && "new_string" in value ) , "WARN" )
15181 }
15282 }
15383
15484 this . parser . onError = ( err : Error ) => {
155- this . log ( "Parser onError callback triggered" , "ERROR" )
156- this . log ( "Error details: " + JSON . stringify ( err ) , "ERROR" )
157- this . log ( "Error message: " + err . message , "ERROR" )
158- this . log ( "Error stack: " + err . stack , "ERROR" )
159-
16085 // Propagate the error to the caller via the callback
161- this . log ( "Calling onErrorCallback with parser error" , "ERROR" )
16286 this . onErrorCallback ( err )
16387 // Note: The @streamparser /json library might throw synchronously on write if onError is not set,
16488 // or if it re-throws. We'll ensure Task.ts wraps write/end in try-catch.
16589 }
166-
167- this . log ( "Constructor completed - parser setup finished" )
168-
169- // Log to console where the debug file is located
170- console . log ( `[StreamingJsonReplacer] Debug logging to file: ${ this . logFilePath } ` )
17190 }
17291
17392 public write ( jsonChunk : string ) : void {
174- this . log ( "write() called" )
175- this . log ( "JSON chunk length: " + jsonChunk . length )
176- this . log ( "JSON chunk preview: " + jsonChunk . substring ( 0 , 200 ) + ( jsonChunk . length > 200 ? "..." : "" ) )
177-
17893 try {
17994 // Errors during write will be caught by the parser's onError or thrown.
180- this . log ( "Calling parser.write()" )
18195 this . parser . write ( jsonChunk )
182- this . log ( "parser.write() completed successfully" )
18396 } catch ( error ) {
184- this . log ( "Exception during parser.write(): " + error , "ERROR" )
18597 throw error
18698 }
18799 }
188100
189101 public getCurrentContent ( ) : string {
190- this . log ( "getCurrentContent() called" )
191- this . log ( "Current content length: " + this . currentFileContent . length )
192102 return this . currentFileContent
193103 }
194104
195105 public getSuccessfullyParsedItems ( ) : ReplacementItem [ ] {
196- this . log ( "getSuccessfullyParsedItems() called" )
197- this . log ( "Returning copy of " + this . successfullyParsedItems . length + " items" )
198106 return [ ...this . successfullyParsedItems ] // Return a copy
199107 }
200108
201109 private calculateChangeLocation ( oldStr : string , newStr : string ) : ChangeLocation {
202- this . log ( "calculateChangeLocation() called" )
203- this . log ( "oldStr length: " + oldStr . length )
204- this . log ( "newStr length: " + newStr . length )
205- this . log ( "oldStr preview: " + oldStr . substring ( 0 , 50 ) + ( oldStr . length > 50 ? "..." : "" ) )
206- this . log ( "newStr preview: " + newStr . substring ( 0 , 50 ) + ( newStr . length > 50 ? "..." : "" ) )
207-
208110 // Find the index where the old string starts
209111 const startIndex = this . currentFileContent . indexOf ( oldStr )
210- this . log ( "startIndex found: " + startIndex )
211112
212113 if ( startIndex === - 1 ) {
213- this . log ( "startIndex is -1 - old string not found in content!" , "WARN" )
214- this . log ( "This shouldn't happen since we already checked includes()" , "WARN" )
215114 // This shouldn't happen since we already checked includes(), but just in case
216115 return { startLine : 0 , endLine : 0 , startChar : 0 , endChar : 0 }
217116 }
218117
219118 // Calculate line numbers by counting newlines before the start index
220119 const contentBeforeStart = this . currentFileContent . substring ( 0 , startIndex )
221- this . log ( "contentBeforeStart length: " + contentBeforeStart . length )
222120
223121 const startLine = ( contentBeforeStart . match ( / \n / g) || [ ] ) . length
224- this . log ( "calculated startLine: " + startLine )
225-
226122 // Calculate the end index after replacement
227123 const endIndex = startIndex + oldStr . length
228- this . log ( "calculated endIndex: " + endIndex )
229124
230125 const contentBeforeEnd = this . currentFileContent . substring ( 0 , endIndex )
231- this . log ( "contentBeforeEnd length: " + contentBeforeEnd . length )
232126
233127 const endLine = ( contentBeforeEnd . match ( / \n / g) || [ ] ) . length
234- this . log ( "calculated endLine: " + endLine )
235-
236128 // Calculate character positions within their respective lines
237129 const lastNewlineBeforeStart = contentBeforeStart . lastIndexOf ( "\n" )
238- this . log ( "lastNewlineBeforeStart: " + lastNewlineBeforeStart )
239-
240130 const startChar = lastNewlineBeforeStart === - 1 ? startIndex : startIndex - lastNewlineBeforeStart - 1
241- this . log ( "calculated startChar: " + startChar )
242131
243132 const lastNewlineBeforeEnd = contentBeforeEnd . lastIndexOf ( "\n" )
244- this . log ( "lastNewlineBeforeEnd: " + lastNewlineBeforeEnd )
245133
246134 const endChar = lastNewlineBeforeEnd === - 1 ? endIndex : endIndex - lastNewlineBeforeEnd - 1
247- this . log ( "calculated endChar: " + endChar )
248135
249136 const result = {
250137 startLine,
@@ -253,20 +140,6 @@ export class StreamingJsonReplacer {
253140 endChar,
254141 }
255142
256- this . log ( "calculateChangeLocation() returning: " + JSON . stringify ( result ) )
257143 return result
258144 }
259-
260- private log ( message : string , level : "INFO" | "WARN" | "ERROR" = "INFO" ) : void {
261- const timestamp = new Date ( ) . toISOString ( )
262- const logLine = `[${ timestamp } ] [${ level } ] ${ message } \n`
263-
264- try {
265- fs . appendFileSync ( this . logFilePath , logLine )
266- } catch ( error ) {
267- // Fallback to console if file logging fails
268- console . error ( "Failed to write to log file:" , error )
269- console . log ( `[${ level } ] ${ message } ` )
270- }
271- }
272145}
0 commit comments