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>
153 lines
3.6 KiB
JavaScript
153 lines
3.6 KiB
JavaScript
'use strict'
|
|
|
|
const { Cache } = require('./cache')
|
|
const { webidl } = require('../webidl')
|
|
const { kEnumerableProperty } = require('../../core/util')
|
|
const { kConstruct } = require('../../core/symbols')
|
|
|
|
class CacheStorage {
|
|
/**
|
|
* @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map
|
|
* @type {Map<string, import('./cache').requestResponseList}
|
|
*/
|
|
#caches = new Map()
|
|
|
|
constructor () {
|
|
if (arguments[0] !== kConstruct) {
|
|
webidl.illegalConstructor()
|
|
}
|
|
|
|
webidl.util.markAsUncloneable(this)
|
|
}
|
|
|
|
async match (request, options = {}) {
|
|
webidl.brandCheck(this, CacheStorage)
|
|
webidl.argumentLengthCheck(arguments, 1, 'CacheStorage.match')
|
|
|
|
request = webidl.converters.RequestInfo(request)
|
|
options = webidl.converters.MultiCacheQueryOptions(options)
|
|
|
|
// 1.
|
|
if (options.cacheName != null) {
|
|
// 1.1.1.1
|
|
if (this.#caches.has(options.cacheName)) {
|
|
// 1.1.1.1.1
|
|
const cacheList = this.#caches.get(options.cacheName)
|
|
const cache = new Cache(kConstruct, cacheList)
|
|
|
|
return await cache.match(request, options)
|
|
}
|
|
} else { // 2.
|
|
// 2.2
|
|
for (const cacheList of this.#caches.values()) {
|
|
const cache = new Cache(kConstruct, cacheList)
|
|
|
|
// 2.2.1.2
|
|
const response = await cache.match(request, options)
|
|
|
|
if (response !== undefined) {
|
|
return response
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-has
|
|
* @param {string} cacheName
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async has (cacheName) {
|
|
webidl.brandCheck(this, CacheStorage)
|
|
|
|
const prefix = 'CacheStorage.has'
|
|
webidl.argumentLengthCheck(arguments, 1, prefix)
|
|
|
|
cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName')
|
|
|
|
// 2.1.1
|
|
// 2.2
|
|
return this.#caches.has(cacheName)
|
|
}
|
|
|
|
/**
|
|
* @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open
|
|
* @param {string} cacheName
|
|
* @returns {Promise<Cache>}
|
|
*/
|
|
async open (cacheName) {
|
|
webidl.brandCheck(this, CacheStorage)
|
|
|
|
const prefix = 'CacheStorage.open'
|
|
webidl.argumentLengthCheck(arguments, 1, prefix)
|
|
|
|
cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName')
|
|
|
|
// 2.1
|
|
if (this.#caches.has(cacheName)) {
|
|
// await caches.open('v1') !== await caches.open('v1')
|
|
|
|
// 2.1.1
|
|
const cache = this.#caches.get(cacheName)
|
|
|
|
// 2.1.1.1
|
|
return new Cache(kConstruct, cache)
|
|
}
|
|
|
|
// 2.2
|
|
const cache = []
|
|
|
|
// 2.3
|
|
this.#caches.set(cacheName, cache)
|
|
|
|
// 2.4
|
|
return new Cache(kConstruct, cache)
|
|
}
|
|
|
|
/**
|
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-delete
|
|
* @param {string} cacheName
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async delete (cacheName) {
|
|
webidl.brandCheck(this, CacheStorage)
|
|
|
|
const prefix = 'CacheStorage.delete'
|
|
webidl.argumentLengthCheck(arguments, 1, prefix)
|
|
|
|
cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName')
|
|
|
|
return this.#caches.delete(cacheName)
|
|
}
|
|
|
|
/**
|
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-keys
|
|
* @returns {Promise<string[]>}
|
|
*/
|
|
async keys () {
|
|
webidl.brandCheck(this, CacheStorage)
|
|
|
|
// 2.1
|
|
const keys = this.#caches.keys()
|
|
|
|
// 2.2
|
|
return [...keys]
|
|
}
|
|
}
|
|
|
|
Object.defineProperties(CacheStorage.prototype, {
|
|
[Symbol.toStringTag]: {
|
|
value: 'CacheStorage',
|
|
configurable: true
|
|
},
|
|
match: kEnumerableProperty,
|
|
has: kEnumerableProperty,
|
|
open: kEnumerableProperty,
|
|
delete: kEnumerableProperty,
|
|
keys: kEnumerableProperty
|
|
})
|
|
|
|
module.exports = {
|
|
CacheStorage
|
|
}
|