814ecac287
The contained consistency consolidations; the sweeping ones are deferred with their standard documented (they're the audit's own post-1.0 refactors, and several would be reckless to do unattended). Landed: - src/main/lib/lineBuffer.ts (createLineBuffer): one newline line-splitter for streamed child-process output, replacing the duplicated buffer loop in download.ts and terminal.ts (CC3/CC4/SIMP5). Pure + unit-tested (test/lineBuffer.test.ts, 7 cases: partial lines, CRLF, empty lines, flush, multi-line chunks). download.ts keeps byte-identical marker parsing and no close-flush (yt-dlp template lines are always newline-terminated). - ytdlp.ts: getYtdlpVersion/updateYtdlp now run stderr through cleanError, the same `cleanError(r.stderr) || r.error?.message || ''` idiom already used by download/probe/indexer (CC6) — a failed check shows the trailing error line. - CL6 resolved: the one real redundancy was L15; clearDir/openFile/showInFolder are deliberate view-model wrappers (CC13), left as-is. Deferred with documented standard + rationale (CODE-AUDIT.md): CC1 (breaking persisted-key rename → migration), CC5+CL4 (security-critical updater net.request, not live-verifiable here), CC7 (cosmetic arg-order), CC9 (zod dep), CC10 (electron-store↔jsonStore split is deliberate for DPAPI), CC11 (config.ts move), CC12 (file-tree reorg), CC13→L93, CC14→L142. Verified: typecheck (node+web) + 275 tests + eslint + production build green; touched files prettier-clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
/**
|
|
* A newline line-splitter for streamed child-process output (audit CC3/CC4/SIMP5).
|
|
*
|
|
* `download.ts` and `terminal.ts` each had the same hand-rolled loop: accumulate
|
|
* chunk strings, emit every complete `\n`-terminated line (stripping a trailing
|
|
* `\r`), and keep the partial remainder for the next chunk. This is that logic in
|
|
* one place, and — being pure and synchronous — it's unit-tested directly.
|
|
*
|
|
* Usage: feed decoded chunks with `push()`, and call `flush()` on stream close to
|
|
* emit any trailing partial line that never saw a newline.
|
|
*/
|
|
export interface LineBuffer {
|
|
/** Accept a decoded chunk; invokes the sink for each newly-completed line. */
|
|
push: (chunk: string) => void
|
|
/** Emit any buffered remainder (a final line with no trailing newline). */
|
|
flush: () => void
|
|
}
|
|
|
|
export function createLineBuffer(onLine: (line: string) => void): LineBuffer {
|
|
let buf = ''
|
|
return {
|
|
push(chunk: string): void {
|
|
buf += chunk
|
|
let nl: number
|
|
while ((nl = buf.indexOf('\n')) >= 0) {
|
|
onLine(buf.slice(0, nl).replace(/\r$/, ''))
|
|
buf = buf.slice(nl + 1)
|
|
}
|
|
},
|
|
flush(): void {
|
|
if (buf) {
|
|
onLine(buf)
|
|
buf = ''
|
|
}
|
|
}
|
|
}
|
|
}
|