Files
AeroFetch/src/main/templates.ts
T
debont80 9134e7d216 feat(audit): Batch 25 — project reorg (CC12), leading DI args (CC7), CC10 by-design
CC12: renderer views/ (5 screens + Onboarding + settings cards) +
lib/ (theme/thumb/datetime/id/qualityOptions/useClipboardLink/queueStats);
main core/ (buildArgs/validation/indexerCore/ytdlpPolicy). git mv preserved
history; all src+test imports updated. Build emits view chunks from views/,
344 tests + typecheck green, live probe rendered all screens.
CC7: wc/onProgress is the leading arg everywhere — downloadAppUpdate(wc,url),
indexSource(onProgress,url,signal), indexSourceCancelable(onProgress,url).
CC10: closed by-design — jsonStore backs all records; settings stay in
electron-store for DPAPI secret encryption (a deliberate two-store split).
Also closes the UI24/W4 context-menu cross-reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 15:37:28 -04:00

45 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { CommandTemplate } from '@shared/ipc'
import { isTemplateLike } from './core/validation'
import { createJsonStore } from './jsonStore'
import { TEMPLATES_MAX } from './constants'
// Plain JSON in userData, same shape as history.ts. Atomic writes / corruption
// backup / caching come from the shared jsonStore (R1R3).
// A persisted template entry must at least be an object carrying an id (see
// isTemplateLike in validation.ts); everything else is coerced by sanitize().
// Drop anything that isn't, so a hand-edited templates.json can't inject
// malformed entries. (audit S5)
const store = createJsonStore('templates.json', isTemplateLike, TEMPLATES_MAX)
export function listTemplates(): CommandTemplate[] {
// Normalise each surviving entry through sanitize() so name/args are always
// well-formed strings regardless of what was on disk.
return store.read().map(sanitize)
}
function sanitize(t: CommandTemplate): CommandTemplate {
const urlPattern = typeof t.urlPattern === 'string' ? t.urlPattern.trim() : ''
return {
id: String(t.id),
name: (t.name ?? '').trim() || 'Untitled command',
args: (t.args ?? '').trim(),
// Only persist a urlPattern when one was provided, keeping older files clean.
...(urlPattern ? { urlPattern } : {})
}
}
/** Add a new template, or update an existing one (matched by id). */
export function saveTemplate(template: CommandTemplate): CommandTemplate[] {
const clean = sanitize(template)
return store.write([clean, ...listTemplates().filter((t) => t.id !== clean.id)])
}
export function removeTemplate(id: string): CommandTemplate[] {
return store.write(listTemplates().filter((t) => t.id !== id))
}
/** Replace the entire template list (backup restore) rather than merge-by-id. */
export function replaceTemplates(templates: CommandTemplate[]): CommandTemplate[] {
return store.write(templates.map(sanitize))
}