tftsr-devops_investigation/node_modules/pump/index.js
Shaun Arman 8839075805 feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.

Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)

Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)

DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload

Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:36:25 -05:00

87 lines
2.2 KiB
JavaScript

var once = require('once')
var eos = require('end-of-stream')
var fs
try {
fs = require('fs') // we only need fs to get the ReadStream and WriteStream prototypes
} catch (e) {}
var noop = function () {}
var ancient = typeof process === 'undefined' ? false : /^v?\.0/.test(process.version)
var isFn = function (fn) {
return typeof fn === 'function'
}
var isFS = function (stream) {
if (!ancient) return false // newer node version do not need to care about fs is a special way
if (!fs) return false // browser
return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close)
}
var isRequest = function (stream) {
return stream.setHeader && isFn(stream.abort)
}
var destroyer = function (stream, reading, writing, callback) {
callback = once(callback)
var closed = false
stream.on('close', function () {
closed = true
})
eos(stream, {readable: reading, writable: writing}, function (err) {
if (err) return callback(err)
closed = true
callback()
})
var destroyed = false
return function (err) {
if (closed) return
if (destroyed) return
destroyed = true
if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks
if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want
if (isFn(stream.destroy)) return stream.destroy()
callback(err || new Error('stream was destroyed'))
}
}
var call = function (fn) {
fn()
}
var pipe = function (from, to) {
return from.pipe(to)
}
var pump = function () {
var streams = Array.prototype.slice.call(arguments)
var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop
if (Array.isArray(streams[0])) streams = streams[0]
if (streams.length < 2) throw new Error('pump requires two streams per minimum')
var error
var destroys = streams.map(function (stream, i) {
var reading = i < streams.length - 1
var writing = i > 0
return destroyer(stream, reading, writing, function (err) {
if (!error) error = err
if (err) destroys.forEach(call)
if (reading) return
destroys.forEach(call)
callback(error)
})
})
return streams.reduce(pipe)
}
module.exports = pump