mirror of
https://github.com/fccview/cronmaster.git
synced 2025-12-23 22:18:20 -05:00
170 lines
4.2 KiB
TypeScript
170 lines
4.2 KiB
TypeScript
import { promises as fs } from "fs";
|
|
import path from "path";
|
|
import { isDocker } from "../_server/actions/global";
|
|
|
|
export interface BashSnippet {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
category: string;
|
|
template: string;
|
|
tags: string[];
|
|
source: "builtin" | "user";
|
|
filePath: string;
|
|
}
|
|
|
|
interface SnippetMetadata {
|
|
id?: string;
|
|
title?: string;
|
|
description?: string;
|
|
category?: string;
|
|
tags?: string[];
|
|
}
|
|
|
|
const parseMetadata = (content: string): SnippetMetadata => {
|
|
const metadata: SnippetMetadata = {};
|
|
const lines = content.split("\n");
|
|
|
|
for (const line of lines) {
|
|
const trimmed = line.trim();
|
|
|
|
const match = trimmed.match(/^#\s*@(\w+):\s*(.+)$/);
|
|
if (match) {
|
|
const [, key, value] = match;
|
|
switch (key) {
|
|
case "id":
|
|
metadata.id = value.trim();
|
|
break;
|
|
case "title":
|
|
metadata.title = value.trim();
|
|
break;
|
|
case "description":
|
|
metadata.description = value.trim();
|
|
break;
|
|
case "category":
|
|
metadata.category = value.trim();
|
|
break;
|
|
case "tags":
|
|
metadata.tags = value.split(",").map((tag) => tag.trim());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return metadata;
|
|
}
|
|
|
|
const extractTemplate = (content: string): string => {
|
|
const lines = content.split("\n");
|
|
const templateLines: string[] = [];
|
|
let inTemplate = false;
|
|
|
|
for (const line of lines) {
|
|
if (line.trim().match(/^#\s*@\w+:/)) {
|
|
continue;
|
|
}
|
|
|
|
if (!inTemplate && line.trim() && !line.trim().startsWith("# @")) {
|
|
inTemplate = true;
|
|
}
|
|
|
|
if (inTemplate) {
|
|
templateLines.push(line);
|
|
}
|
|
}
|
|
|
|
return templateLines.join("\n").trim();
|
|
}
|
|
|
|
const scanSnippetDirectory = async (
|
|
dirPath: string,
|
|
source: "builtin" | "user"
|
|
): Promise<BashSnippet[]> => {
|
|
const snippets: BashSnippet[] = [];
|
|
|
|
try {
|
|
const files = await fs.readdir(dirPath);
|
|
|
|
for (const file of files) {
|
|
if (file.endsWith(".sh")) {
|
|
const filePath = path.join(dirPath, file);
|
|
const content = await fs.readFile(filePath, "utf-8");
|
|
const metadata = parseMetadata(content);
|
|
const template = extractTemplate(content);
|
|
|
|
if (
|
|
metadata.id &&
|
|
metadata.title &&
|
|
metadata.description &&
|
|
metadata.category
|
|
) {
|
|
snippets.push({
|
|
id: metadata.id,
|
|
title: metadata.title,
|
|
description: metadata.description,
|
|
category: metadata.category,
|
|
template,
|
|
tags: metadata.tags || [],
|
|
source,
|
|
filePath,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.warn(`Warning: Could not scan directory ${dirPath}:`, error);
|
|
}
|
|
|
|
return snippets;
|
|
}
|
|
|
|
export const loadAllSnippets = async (): Promise<BashSnippet[]> => {
|
|
const docker = await isDocker();
|
|
|
|
let builtinSnippetsPath: string;
|
|
let userSnippetsPath: string;
|
|
|
|
if (docker) {
|
|
builtinSnippetsPath = "/app/app/_utils/snippets";
|
|
userSnippetsPath = "/app/snippets";
|
|
} else {
|
|
builtinSnippetsPath = path.join(process.cwd(), "app", "_utils", "snippets");
|
|
userSnippetsPath = path.join(process.cwd(), "snippets");
|
|
}
|
|
|
|
const builtinSnippets = await scanSnippetDirectory(
|
|
builtinSnippetsPath,
|
|
"builtin"
|
|
);
|
|
|
|
const userSnippets = await scanSnippetDirectory(userSnippetsPath, "user");
|
|
|
|
return [...builtinSnippets, ...userSnippets];
|
|
}
|
|
|
|
export const searchBashSnippets = (
|
|
snippets: BashSnippet[],
|
|
query: string
|
|
): BashSnippet[] => {
|
|
const lowercaseQuery = query.toLowerCase();
|
|
return snippets.filter(
|
|
(snippet) =>
|
|
snippet.title.toLowerCase().includes(lowercaseQuery) ||
|
|
snippet.description.toLowerCase().includes(lowercaseQuery) ||
|
|
snippet.tags.some((tag) => tag.toLowerCase().includes(lowercaseQuery)) ||
|
|
snippet.category.toLowerCase().includes(lowercaseQuery)
|
|
);
|
|
}
|
|
|
|
export const getSnippetCategories = (snippets: BashSnippet[]): string[] => {
|
|
const categories = new Set(snippets.map((snippet) => snippet.category));
|
|
return Array.from(categories).sort();
|
|
}
|
|
|
|
export const getSnippetById = (
|
|
snippets: BashSnippet[],
|
|
id: string
|
|
): BashSnippet | undefined => {
|
|
return snippets.find((snippet) => snippet.id === id);
|
|
}
|