(slug: string)
| 422 | /** Delete a custom theme folder. Refuses anything that isn't a bare slug |
| 423 | * resolving to a direct child of the themes dir (no path traversal). */ |
| 424 | export async function deleteCustomTheme(slug: string): Promise<void> { |
| 425 | if (!isSafeSlug(slug)) return |
| 426 | const dir = getCustomThemesDir() |
| 427 | const folder = path.join(dir, slug) |
| 428 | if (path.dirname(path.resolve(folder)) !== path.resolve(dir)) return |
| 429 | await fs.rm(folder, { recursive: true, force: true }).catch(() => {}) |
| 430 | } |
| 431 | |
| 432 | /** Synchronous existence check used by the reveal handler's mkdir fallback. */ |
| 433 | export function customThemesDirExistsSync(): boolean { |
no test coverage detected