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>
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
/**
|
||
* Handle values based on a field.
|
||
*
|
||
* @template {InvalidHandler} [Invalid=InvalidHandler]
|
||
* @template {UnknownHandler} [Unknown=UnknownHandler]
|
||
* @template {Record<string, Handler>} [Handlers=Record<string, Handler>]
|
||
* @param {string} key
|
||
* Field to switch on.
|
||
* @param {Options<Invalid, Unknown, Handlers>} [options]
|
||
* Configuration (required).
|
||
* @returns {{unknown: Unknown, invalid: Invalid, handlers: Handlers, (...parameters: Parameters<Handlers[keyof Handlers]>): ReturnType<Handlers[keyof Handlers]>, (...parameters: Parameters<Unknown>): ReturnType<Unknown>}}
|
||
*/
|
||
export function zwitch<
|
||
Invalid extends InvalidHandler = InvalidHandler,
|
||
Unknown extends UnknownHandler = UnknownHandler,
|
||
Handlers extends Record<string, Handler> = Record<string, Handler>
|
||
>(
|
||
key: string,
|
||
options?: Options<Invalid, Unknown, Handlers> | undefined
|
||
): {
|
||
(...parameters: Parameters<Handlers[keyof Handlers]>): ReturnType<
|
||
Handlers[keyof Handlers]
|
||
>
|
||
(...parameters: Parameters<Unknown>): ReturnType<Unknown>
|
||
unknown: Unknown
|
||
invalid: Invalid
|
||
handlers: Handlers
|
||
}
|
||
/**
|
||
* Handle a value, with a certain ID field set to a certain value.
|
||
* The ID field is passed to `zwitch`, and it’s value is this function’s
|
||
* place on the `handlers` record.
|
||
*/
|
||
export type Handler = (...parameters: any[]) => any
|
||
/**
|
||
* Handle values that do have a certain ID field, but it’s set to a value
|
||
* that is not listed in the `handlers` record.
|
||
*/
|
||
export type UnknownHandler = (value: unknown, ...rest: any[]) => any
|
||
/**
|
||
* Handle values that do not have a certain ID field.
|
||
*/
|
||
export type InvalidHandler = (
|
||
value: unknown,
|
||
...rest: any[]
|
||
) => void | null | undefined | never
|
||
/**
|
||
* Configuration (required).
|
||
*/
|
||
export type Options<
|
||
Invalid extends InvalidHandler = InvalidHandler,
|
||
Unknown extends UnknownHandler = UnknownHandler,
|
||
Handlers extends Record<string, Handler> = Record<string, Handler>
|
||
> = {
|
||
/**
|
||
* Handler to use for invalid values.
|
||
*/
|
||
invalid?: Invalid | undefined
|
||
/**
|
||
* Handler to use for unknown values.
|
||
*/
|
||
unknown?: Unknown | undefined
|
||
/**
|
||
* Handlers to use.
|
||
*/
|
||
handlers?: Handlers | undefined
|
||
}
|