mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge pull request #1617 from Dokploy/fix/cover-edge-cases-processor-template
fix(templates): add optional chaining to prevent errors when accessin…
This commit is contained in:
commit
131a1acbbe
@ -307,7 +307,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
>
|
>
|
||||||
{templates?.map((template) => (
|
{templates?.map((template) => (
|
||||||
<div
|
<div
|
||||||
key={template.id}
|
key={template?.id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col border rounded-lg overflow-hidden relative",
|
"flex flex-col border rounded-lg overflow-hidden relative",
|
||||||
viewMode === "icon" && "h-[200px]",
|
viewMode === "icon" && "h-[200px]",
|
||||||
@ -315,7 +315,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Badge className="absolute top-2 right-2" variant="blue">
|
<Badge className="absolute top-2 right-2" variant="blue">
|
||||||
{template.version}
|
{template?.version}
|
||||||
</Badge>
|
</Badge>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -324,21 +324,21 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={`${customBaseUrl || "https://templates.dokploy.com/"}/blueprints/${template.id}/${template.logo}`}
|
src={`${customBaseUrl || "https://templates.dokploy.com/"}/blueprints/${template?.id}/${template?.logo}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
"object-contain",
|
"object-contain",
|
||||||
viewMode === "detailed" ? "size-24" : "size-16",
|
viewMode === "detailed" ? "size-24" : "size-16",
|
||||||
)}
|
)}
|
||||||
alt={template.name}
|
alt={template?.name}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col items-center gap-2">
|
<div className="flex flex-col items-center gap-2">
|
||||||
<span className="text-sm font-medium line-clamp-1">
|
<span className="text-sm font-medium line-clamp-1">
|
||||||
{template.name}
|
{template?.name}
|
||||||
</span>
|
</span>
|
||||||
{viewMode === "detailed" &&
|
{viewMode === "detailed" &&
|
||||||
template.tags.length > 0 && (
|
template?.tags?.length > 0 && (
|
||||||
<div className="flex flex-wrap justify-center gap-1.5">
|
<div className="flex flex-wrap justify-center gap-1.5">
|
||||||
{template.tags.map((tag) => (
|
{template?.tags?.map((tag) => (
|
||||||
<Badge
|
<Badge
|
||||||
key={tag}
|
key={tag}
|
||||||
variant="green"
|
variant="green"
|
||||||
@ -356,7 +356,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
{viewMode === "detailed" && (
|
{viewMode === "detailed" && (
|
||||||
<ScrollArea className="flex-1 p-6">
|
<ScrollArea className="flex-1 p-6">
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
{template.description}
|
{template?.description}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
)}
|
)}
|
||||||
@ -372,25 +372,27 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
>
|
>
|
||||||
{viewMode === "detailed" && (
|
{viewMode === "detailed" && (
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Link
|
{template?.links?.github && (
|
||||||
href={template.links.github}
|
|
||||||
target="_blank"
|
|
||||||
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
||||||
>
|
|
||||||
<GithubIcon className="size-5" />
|
|
||||||
</Link>
|
|
||||||
{template.links.website && (
|
|
||||||
<Link
|
<Link
|
||||||
href={template.links.website}
|
href={template?.links?.github}
|
||||||
|
target="_blank"
|
||||||
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
<GithubIcon className="size-5" />
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{template?.links?.website && (
|
||||||
|
<Link
|
||||||
|
href={template?.links?.website}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="text-muted-foreground hover:text-foreground transition-colors"
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
||||||
>
|
>
|
||||||
<Globe className="size-5" />
|
<Globe className="size-5" />
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{template.links.docs && (
|
{template?.links?.docs && (
|
||||||
<Link
|
<Link
|
||||||
href={template.links.docs}
|
href={template?.links?.docs}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="text-muted-foreground hover:text-foreground transition-colors"
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
||||||
>
|
>
|
||||||
@ -419,7 +421,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
This will create an application from the{" "}
|
This will create an application from the{" "}
|
||||||
{template.name} template and add it to your
|
{template?.name} template and add it to your
|
||||||
project.
|
project.
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { faker } from "@faker-js/faker";
|
||||||
import type { Schema } from "./index";
|
import type { Schema } from "./index";
|
||||||
import {
|
import {
|
||||||
generateBase64,
|
generateBase64,
|
||||||
@ -70,7 +71,7 @@ function processValue(
|
|||||||
schema: Schema,
|
schema: Schema,
|
||||||
): string {
|
): string {
|
||||||
// First replace utility functions
|
// First replace utility functions
|
||||||
let processedValue = value.replace(/\${([^}]+)}/g, (match, varName) => {
|
let processedValue = value?.replace(/\${([^}]+)}/g, (match, varName) => {
|
||||||
// Handle utility functions
|
// Handle utility functions
|
||||||
if (varName === "domain") {
|
if (varName === "domain") {
|
||||||
return generateRandomDomain(schema);
|
return generateRandomDomain(schema);
|
||||||
@ -117,6 +118,14 @@ function processValue(
|
|||||||
return generateJwt(length);
|
return generateJwt(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (varName === "username") {
|
||||||
|
return faker.internet.userName().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (varName === "email") {
|
||||||
|
return faker.internet.email().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
// If not a utility function, try to get from variables
|
// If not a utility function, try to get from variables
|
||||||
return variables[varName] || match;
|
return variables[varName] || match;
|
||||||
});
|
});
|
||||||
@ -177,7 +186,14 @@ export function processDomains(
|
|||||||
variables: Record<string, string>,
|
variables: Record<string, string>,
|
||||||
schema: Schema,
|
schema: Schema,
|
||||||
): Template["domains"] {
|
): Template["domains"] {
|
||||||
if (!template?.config?.domains) return [];
|
if (
|
||||||
|
!template?.config?.domains ||
|
||||||
|
template.config.domains.length === 0 ||
|
||||||
|
template.config.domains.every((domain) => !domain.serviceName)
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return template?.config?.domains?.map((domain: DomainConfig) => ({
|
return template?.config?.domains?.map((domain: DomainConfig) => ({
|
||||||
...domain,
|
...domain,
|
||||||
host: domain.host
|
host: domain.host
|
||||||
@ -194,7 +210,9 @@ export function processEnvVars(
|
|||||||
variables: Record<string, string>,
|
variables: Record<string, string>,
|
||||||
schema: Schema,
|
schema: Schema,
|
||||||
): Template["envs"] {
|
): Template["envs"] {
|
||||||
if (!template?.config?.env) return [];
|
if (!template?.config?.env || Object.keys(template.config.env).length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// Handle array of env vars
|
// Handle array of env vars
|
||||||
if (Array.isArray(template.config.env)) {
|
if (Array.isArray(template.config.env)) {
|
||||||
@ -233,7 +251,13 @@ export function processMounts(
|
|||||||
variables: Record<string, string>,
|
variables: Record<string, string>,
|
||||||
schema: Schema,
|
schema: Schema,
|
||||||
): Template["mounts"] {
|
): Template["mounts"] {
|
||||||
if (!template?.config?.mounts) return [];
|
if (
|
||||||
|
!template?.config?.mounts ||
|
||||||
|
template.config.mounts.length === 0 ||
|
||||||
|
template.config.mounts.every((mount) => !mount.filePath && !mount.content)
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return template?.config?.mounts?.map((mount: MountConfig) => ({
|
return template?.config?.mounts?.map((mount: MountConfig) => ({
|
||||||
filePath: processValue(mount.filePath, variables, schema),
|
filePath: processValue(mount.filePath, variables, schema),
|
||||||
|
Loading…
Reference in New Issue
Block a user