tftsr-devops_investigation/node_modules/bare-path/lib/posix.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

243 lines
5.9 KiB
JavaScript

const os = require('bare-os')
const { normalizeString } = require('./shared')
const {
CHAR_DOT,
CHAR_FORWARD_SLASH
} = require('./constants')
function isPosixPathSeparator (code) {
return code === CHAR_FORWARD_SLASH
}
exports.win32 = require('./win32')
exports.posix = exports
exports.sep = '/'
exports.delimiter = ':'
exports.resolve = function resolve (...args) {
let resolvedPath = ''
let resolvedAbsolute = false
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
const path = i >= 0 ? args[i] : os.cwd()
if (path.length === 0) {
continue
}
resolvedPath = `${path}/${resolvedPath}`
resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH
}
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', isPosixPathSeparator)
if (resolvedAbsolute) {
return `/${resolvedPath}`
}
return resolvedPath.length > 0 ? resolvedPath : '.'
}
exports.normalize = function normalize (path) {
if (path.length === 0) return '.'
const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH
const trailingSeparator = path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH
path = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator)
if (path.length === 0) {
if (isAbsolute) return '/'
return trailingSeparator ? './' : '.'
}
if (trailingSeparator) path += '/'
return isAbsolute ? `/${path}` : path
}
exports.isAbsolute = function isAbsolute (path) {
return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH
}
exports.join = function join (...args) {
if (args.length === 0) return '.'
let joined
for (let i = 0; i < args.length; ++i) {
const arg = args[i]
if (arg.length > 0) {
if (joined === undefined) joined = arg
else joined += `/${arg}`
}
}
if (joined === undefined) return '.'
return exports.normalize(joined)
}
exports.relative = function relative (from, to) {
if (from === to) return ''
from = exports.resolve(from)
to = exports.resolve(to)
if (from === to) return ''
const fromStart = 1
const fromEnd = from.length
const fromLen = fromEnd - fromStart
const toStart = 1
const toLen = to.length - toStart
const length = (fromLen < toLen ? fromLen : toLen)
let lastCommonSep = -1
let i = 0
for (; i < length; i++) {
const fromCode = from.charCodeAt(fromStart + i)
if (fromCode !== to.charCodeAt(toStart + i)) {
break
} else if (fromCode === CHAR_FORWARD_SLASH) {
lastCommonSep = i
}
}
if (i === length) {
if (toLen > length) {
if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {
return to.substring(toStart + i + 1)
}
if (i === 0) {
return to.substring(toStart + i)
}
} else if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {
lastCommonSep = i
} else if (i === 0) {
lastCommonSep = 0
}
}
}
let out = ''
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) {
out += out.length === 0 ? '..' : '/..'
}
}
return `${out}${to.substring(toStart + lastCommonSep)}`
}
exports.toNamespacedPath = function toNamespacedPath (path) {
return path
}
exports.dirname = function dirname (path) {
if (path.length === 0) return '.'
const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH
let end = -1
let matchedSlash = true
for (let i = path.length - 1; i >= 1; --i) {
if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
end = i
break
}
} else {
matchedSlash = false
}
}
if (end === -1) return hasRoot ? '/' : '.'
if (hasRoot && end === 1) return '//'
return path.substring(0, end)
}
exports.basename = function basename (path, suffix) {
let start = 0
let end = -1
let matchedSlash = true
if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) {
if (suffix === path) { return '' }
let extIdx = suffix.length - 1
let firstNonSlashEnd = -1
for (let i = path.length - 1; i >= 0; --i) {
const code = path.charCodeAt(i)
if (code === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
start = i + 1
break
}
} else {
if (firstNonSlashEnd === -1) {
matchedSlash = false
firstNonSlashEnd = i + 1
}
if (extIdx >= 0) {
if (code === suffix.charCodeAt(extIdx)) {
if (--extIdx === -1) {
end = i
}
} else {
extIdx = -1
end = firstNonSlashEnd
}
}
}
}
if (start === end) end = firstNonSlashEnd
else if (end === -1) end = path.length
return path.substring(start, end)
}
for (let i = path.length - 1; i >= 0; --i) {
if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
start = i + 1
break
}
} else if (end === -1) {
matchedSlash = false
end = i + 1
}
}
if (end === -1) return ''
return path.substring(start, end)
}
exports.extname = function extname (path) {
let startDot = -1
let startPart = 0
let end = -1
let matchedSlash = true
let preDotState = 0
for (let i = path.length - 1; i >= 0; --i) {
const code = path.charCodeAt(i)
if (code === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
startPart = i + 1
break
}
continue
}
if (end === -1) {
matchedSlash = false
end = i + 1
}
if (code === CHAR_DOT) {
if (startDot === -1) startDot = i
else if (preDotState !== 1) preDotState = 1
} else if (startDot !== -1) {
preDotState = -1
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {
return ''
}
return path.substring(startDot, end)
}