mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-10-15 21:31:11 +00:00
6e1d020769
- Updated ShowIconSettings component to handle both application and compose service types. - Added new icon column to the compose table in the database. - Implemented fetching and updating of icons for services in the environment and application pages. - Introduced fetchTemplateLogo function to retrieve logos for templates, improving icon handling for compose services.
150 lines
3.5 KiB
TypeScript
150 lines
3.5 KiB
TypeScript
import { parse } from "toml";
|
|
|
|
/**
|
|
* Complete template interface that includes both metadata and configuration
|
|
*/
|
|
export interface CompleteTemplate {
|
|
metadata: {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
tags: string[];
|
|
version: string;
|
|
logo: string;
|
|
links: {
|
|
github: string;
|
|
website?: string;
|
|
docs?: string;
|
|
};
|
|
};
|
|
variables: {
|
|
[key: string]: string;
|
|
};
|
|
config: {
|
|
isolated?: boolean;
|
|
domains: Array<{
|
|
serviceName: string;
|
|
port: number;
|
|
path?: string;
|
|
host?: string;
|
|
}>;
|
|
env: Record<string, string>;
|
|
mounts?: Array<{
|
|
filePath: string;
|
|
content: string;
|
|
}>;
|
|
};
|
|
}
|
|
|
|
interface TemplateMetadata {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
version: string;
|
|
logo: string;
|
|
links: {
|
|
github: string;
|
|
website?: string;
|
|
docs?: string;
|
|
};
|
|
tags: string[];
|
|
}
|
|
|
|
/**
|
|
* Fetches the list of available templates from meta.json
|
|
*/
|
|
export async function fetchTemplatesList(
|
|
baseUrl = "https://templates.dokploy.com",
|
|
): Promise<TemplateMetadata[]> {
|
|
const response = await fetch(`${baseUrl}/meta.json`, {
|
|
signal: AbortSignal.timeout(10000),
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
}
|
|
const templates = (await response.json()) as TemplateMetadata[];
|
|
return templates.map((template) => ({
|
|
id: template.id,
|
|
name: template.name,
|
|
description: template.description,
|
|
version: template.version,
|
|
logo: template.logo,
|
|
links: template.links,
|
|
tags: template.tags,
|
|
}));
|
|
}
|
|
|
|
const LOGO_MIME_TYPES: Record<string, string> = {
|
|
png: "image/png",
|
|
jpg: "image/jpeg",
|
|
jpeg: "image/jpeg",
|
|
svg: "image/svg+xml",
|
|
webp: "image/webp",
|
|
gif: "image/gif",
|
|
};
|
|
|
|
export async function fetchTemplateLogo(
|
|
templateId: string,
|
|
baseUrl = "https://templates.dokploy.com",
|
|
): Promise<string | null> {
|
|
try {
|
|
const templates = await fetchTemplatesList(baseUrl);
|
|
const template = templates.find((t) => t.id === templateId);
|
|
if (!template?.logo) return null;
|
|
|
|
const response = await fetch(
|
|
`${baseUrl}/blueprints/${templateId}/${template.logo}`,
|
|
{ signal: AbortSignal.timeout(10000) },
|
|
);
|
|
if (!response.ok) return null;
|
|
|
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
if (buffer.length === 0) return null;
|
|
|
|
const contentType = response.headers.get("content-type")?.split(";")[0];
|
|
const extension = template.logo.split(".").pop()?.toLowerCase() ?? "";
|
|
const mimeType = contentType?.startsWith("image/")
|
|
? contentType
|
|
: LOGO_MIME_TYPES[extension];
|
|
if (!mimeType) return null;
|
|
|
|
const dataUrl = `data:${mimeType};base64,${buffer.toString("base64")}`;
|
|
if (dataUrl.length > 2 * 1024 * 1024) return null;
|
|
|
|
return dataUrl;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches a specific template's files
|
|
*/
|
|
export async function fetchTemplateFiles(
|
|
templateId: string,
|
|
baseUrl = "https://templates.dokploy.com",
|
|
): Promise<{ config: CompleteTemplate; dockerCompose: string }> {
|
|
const timeout = AbortSignal.timeout(10000);
|
|
const [templateYmlResponse, dockerComposeResponse] = await Promise.all([
|
|
fetch(`${baseUrl}/blueprints/${templateId}/template.toml`, {
|
|
signal: timeout,
|
|
}),
|
|
fetch(`${baseUrl}/blueprints/${templateId}/docker-compose.yml`, {
|
|
signal: timeout,
|
|
}),
|
|
]);
|
|
|
|
if (!templateYmlResponse.ok || !dockerComposeResponse.ok) {
|
|
throw new Error("Template files not found");
|
|
}
|
|
|
|
const [templateYml, dockerCompose] = await Promise.all([
|
|
templateYmlResponse.text(),
|
|
dockerComposeResponse.text(),
|
|
]);
|
|
|
|
const config = parse(templateYml) as CompleteTemplate;
|
|
|
|
return { config, dockerCompose };
|
|
}
|