diff --git a/apps/dokploy/components/dashboard/application/advanced/traefik/update-traefik-config.tsx b/apps/dokploy/components/dashboard/application/advanced/traefik/update-traefik-config.tsx index 73512837f..bf3d5d9bc 100644 --- a/apps/dokploy/components/dashboard/application/advanced/traefik/update-traefik-config.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/traefik/update-traefik-config.tsx @@ -1,8 +1,8 @@ import { zodResolver } from "@hookform/resolvers/zod"; -import jsyaml from "js-yaml"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; +import { parse, stringify, YAMLParseError } from "yaml"; import { z } from "zod"; import { AlertBlock } from "@/components/shared/alert-block"; import { CodeEditor } from "@/components/shared/code-editor"; @@ -38,11 +38,11 @@ interface Props { export const validateAndFormatYAML = (yamlText: string) => { try { - const obj = jsyaml.load(yamlText); - const formattedYaml = jsyaml.dump(obj, { indent: 4 }); + const obj = parse(yamlText); + const formattedYaml = stringify(obj, { indent: 4 }); return { valid: true, formattedYaml, error: null }; } catch (error) { - if (error instanceof jsyaml.YAMLException) { + if (error instanceof YAMLParseError) { return { valid: false, formattedYaml: yamlText, @@ -89,7 +89,7 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => { if (!valid) { form.setError("traefikConfig", { type: "manual", - message: error || "Invalid YAML", + message: (error as string) || "Invalid YAML", }); return; } diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index 68958907c..cfaeaa5ba 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -112,7 +112,7 @@ "i18next": "^23.16.8", "input-otp": "^1.4.2", "js-cookie": "^3.0.5", - "js-yaml": "4.1.0", + "yaml": "2.8.1", "lodash": "4.17.21", "lucide-react": "^0.469.0", "micromatch": "4.0.8", @@ -160,7 +160,6 @@ "@types/adm-zip": "^0.5.7", "@types/bcrypt": "5.0.2", "@types/js-cookie": "^3.0.6", - "@types/js-yaml": "4.0.9", "@types/lodash": "4.17.4", "@types/micromatch": "4.0.9", "@types/node": "^18.19.104", diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index 64f844faf..512ea9718 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -39,10 +39,10 @@ import { import { processTemplate } from "@dokploy/server/templates/processors"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; -import { dump } from "js-yaml"; import _ from "lodash"; import { nanoid } from "nanoid"; import { parse } from "toml"; +import { stringify } from "yaml"; import { z } from "zod"; import { slugify } from "@/lib/slug"; import { db } from "@/server/db"; @@ -364,7 +364,7 @@ export const composeRouter = createTRPCRouter({ } const domains = await findDomainsByComposeId(input.composeId); const composeFile = await addDomainToCompose(compose, domains); - return dump(composeFile, { + return stringify(composeFile, { lineWidth: 1000, }); }), diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 02678b990..b4968c260 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -46,8 +46,8 @@ import { import { generateOpenApiDocument } from "@dokploy/trpc-openapi"; import { TRPCError } from "@trpc/server"; import { eq, sql } from "drizzle-orm"; -import { dump, load } from "js-yaml"; import { scheduledJobs, scheduleJob } from "node-schedule"; +import { parse, stringify } from "yaml"; import { z } from "zod"; import { db } from "@/server/db"; import { @@ -657,7 +657,7 @@ export const settingsRouter = createTRPCRouter({ const config = readMainConfig(); if (!config) return false; - const parsedConfig = load(config) as { + const parsedConfig = parse(config) as { accessLog?: { filePath: string; }; @@ -678,7 +678,7 @@ export const settingsRouter = createTRPCRouter({ const mainConfig = readMainConfig(); if (!mainConfig) return false; - const currentConfig = load(mainConfig) as { + const currentConfig = parse(mainConfig) as { accessLog?: { filePath: string; }; @@ -701,7 +701,7 @@ export const settingsRouter = createTRPCRouter({ currentConfig.accessLog = undefined; } - writeMainConfig(dump(currentConfig)); + writeMainConfig(stringify(currentConfig)); return true; }), diff --git a/packages/server/package.json b/packages/server/package.json index 3b249a65b..4d0f2e804 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -57,7 +57,7 @@ "drizzle-orm": "^0.39.3", "drizzle-zod": "0.5.1", "hi-base32": "^0.5.1", - "js-yaml": "4.1.0", + "yaml": "2.8.1", "lodash": "4.17.21", "micromatch": "4.0.8", "nanoid": "3.3.11", @@ -85,7 +85,6 @@ "@types/adm-zip": "^0.5.7", "@types/bcrypt": "5.0.2", "@types/dockerode": "3.3.23", - "@types/js-yaml": "4.0.9", "@types/lodash": "4.17.4", "@types/micromatch": "4.0.9", "@types/node": "^18.19.104", diff --git a/packages/server/src/services/certificate.ts b/packages/server/src/services/certificate.ts index f59f1c2aa..8707d098a 100644 --- a/packages/server/src/services/certificate.ts +++ b/packages/server/src/services/certificate.ts @@ -9,7 +9,7 @@ import { import { removeDirectoryIfExistsContent } from "@dokploy/server/utils/filesystem/directory"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; -import { dump } from "js-yaml"; +import { stringify } from "yaml"; import type { z } from "zod"; import { encodeBase64 } from "../utils/docker/utils"; import { execAsyncRemote } from "../utils/process/execAsync"; @@ -101,7 +101,7 @@ const createCertificateFiles = async (certificate: Certificate) => { ], }, }; - const yamlConfig = dump(traefikConfig); + const yamlConfig = stringify(traefikConfig); const configFile = path.join(certDir, "certificate.yml"); if (certificate.serverId) { diff --git a/packages/server/src/setup/traefik-setup.ts b/packages/server/src/setup/traefik-setup.ts index c11e409c5..fa9bf78d0 100644 --- a/packages/server/src/setup/traefik-setup.ts +++ b/packages/server/src/setup/traefik-setup.ts @@ -8,7 +8,7 @@ import { } from "node:fs"; import path from "node:path"; import type { ContainerCreateOptions, CreateServiceOptions } from "dockerode"; -import { dump } from "js-yaml"; +import { stringify } from "yaml"; import { paths } from "../constants"; import { getRemoteDocker } from "../utils/servers/remote-docker"; import type { FileConfig } from "../utils/traefik/file-types"; @@ -241,7 +241,7 @@ export const createDefaultServerTraefikConfig = () => { }, }; - const yamlStr = dump(config); + const yamlStr = stringify(config); mkdirSync(DYNAMIC_TRAEFIK_PATH, { recursive: true }); writeFileSync( path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`), @@ -315,7 +315,7 @@ export const getDefaultTraefikConfig = () => { }), }; - const yamlStr = dump(configObject); + const yamlStr = stringify(configObject); return yamlStr; }; @@ -369,7 +369,7 @@ export const getDefaultServerTraefikConfig = () => { }, }; - const yamlStr = dump(configObject); + const yamlStr = stringify(configObject); return yamlStr; }; @@ -417,7 +417,7 @@ export const getDefaultMiddlewares = () => { }, }, }; - const yamlStr = dump(defaultMiddlewares); + const yamlStr = stringify(defaultMiddlewares); return yamlStr; }; export const createDefaultMiddlewares = () => { diff --git a/packages/server/src/utils/docker/collision.ts b/packages/server/src/utils/docker/collision.ts index de6d9bbb3..9752100ca 100644 --- a/packages/server/src/utils/docker/collision.ts +++ b/packages/server/src/utils/docker/collision.ts @@ -1,5 +1,5 @@ import { findComposeById } from "@dokploy/server/services/compose"; -import { dump } from "js-yaml"; +import { stringify } from "yaml"; import { addAppNameToAllServiceNames } from "./collision/root-network"; import { generateRandomHash } from "./compose"; import { addSuffixToAllVolumes } from "./compose/volume"; @@ -59,7 +59,7 @@ export const randomizeIsolatedDeploymentComposeFile = async ( ) : composeData; - return dump(newComposeFile); + return stringify(newComposeFile); }; export const randomizeDeployableSpecificationFile = ( diff --git a/packages/server/src/utils/docker/compose.ts b/packages/server/src/utils/docker/compose.ts index 2cb909abb..a78b416ec 100644 --- a/packages/server/src/utils/docker/compose.ts +++ b/packages/server/src/utils/docker/compose.ts @@ -1,6 +1,6 @@ import crypto from "node:crypto"; import { findComposeById } from "@dokploy/server/services/compose"; -import { dump, load } from "js-yaml"; +import { parse, stringify } from "yaml"; import { addSuffixToAllConfigs } from "./compose/configs"; import { addSuffixToAllNetworks } from "./compose/network"; import { addSuffixToAllSecrets } from "./compose/secrets"; @@ -18,13 +18,13 @@ export const randomizeComposeFile = async ( ) => { const compose = await findComposeById(composeId); const composeFile = compose.composeFile; - const composeData = load(composeFile) as ComposeSpecification; + const composeData = parse(composeFile) as ComposeSpecification; const randomSuffix = suffix || generateRandomHash(); const newComposeFile = addSuffixToAllProperties(composeData, randomSuffix); - return dump(newComposeFile); + return stringify(newComposeFile); }; export const randomizeSpecificationFile = ( diff --git a/packages/server/src/utils/docker/domain.ts b/packages/server/src/utils/docker/domain.ts index cfb74e974..7a9521d1d 100644 --- a/packages/server/src/utils/docker/domain.ts +++ b/packages/server/src/utils/docker/domain.ts @@ -4,7 +4,7 @@ import { join } from "node:path"; import { paths } from "@dokploy/server/constants"; import type { Compose } from "@dokploy/server/services/compose"; import type { Domain } from "@dokploy/server/services/domain"; -import { dump, load } from "js-yaml"; +import { parse, stringify } from "yaml"; import { execAsyncRemote } from "../process/execAsync"; import { cloneRawBitbucketRepository, @@ -92,7 +92,7 @@ export const loadDockerCompose = async ( if (existsSync(path)) { const yamlStr = readFileSync(path, "utf8"); - const parsedConfig = load(yamlStr) as ComposeSpecification; + const parsedConfig = parse(yamlStr) as ComposeSpecification; return parsedConfig; } return null; @@ -115,7 +115,7 @@ export const loadDockerComposeRemote = async ( return null; } if (!stdout) return null; - const parsedConfig = load(stdout) as ComposeSpecification; + const parsedConfig = parse(stdout) as ComposeSpecification; return parsedConfig; } catch { return null; @@ -141,7 +141,7 @@ export const writeDomainsToCompose = async ( const composeConverted = await addDomainToCompose(compose, domains); const path = getComposePath(compose); - const composeString = dump(composeConverted, { lineWidth: 1000 }); + const composeString = stringify(composeConverted, { lineWidth: 1000 }); try { await writeFile(path, composeString, "utf8"); } catch (error) { @@ -169,7 +169,7 @@ exit 1; `; } if (compose.serverId) { - const composeString = dump(composeConverted, { lineWidth: 1000 }); + const composeString = stringify(composeConverted, { lineWidth: 1000 }); const encodedContent = encodeBase64(composeString); return `echo "${encodedContent}" | base64 -d > "${path}";`; } @@ -287,7 +287,7 @@ export const writeComposeFile = async ( const path = getComposePath(compose); try { - const composeFile = dump(composeSpec, { + const composeFile = stringify(composeSpec, { lineWidth: 1000, }); fs.writeFileSync(path, composeFile, "utf8"); diff --git a/packages/server/src/utils/traefik/application.ts b/packages/server/src/utils/traefik/application.ts index cd2c30a1f..b18161c76 100644 --- a/packages/server/src/utils/traefik/application.ts +++ b/packages/server/src/utils/traefik/application.ts @@ -3,7 +3,7 @@ import path from "node:path"; import { createInterface } from "node:readline"; import { paths } from "@dokploy/server/constants"; import type { Domain } from "@dokploy/server/services/domain"; -import { dump, load } from "js-yaml"; +import { parse, stringify } from "yaml"; import { encodeBase64 } from "../docker/utils"; import { execAsyncRemote } from "../process/execAsync"; import type { FileConfig, HttpLoadBalancerService } from "./file-types"; @@ -40,7 +40,7 @@ export const createTraefikConfig = (appName: string) => { }, }, }; - const yamlStr = dump(config); + const yamlStr = stringify(config); const { DYNAMIC_TRAEFIK_PATH } = paths(); fs.mkdirSync(DYNAMIC_TRAEFIK_PATH, { recursive: true }); writeFileSync( @@ -87,7 +87,7 @@ export const loadOrCreateConfig = (appName: string): FileConfig => { const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); if (fs.existsSync(configPath)) { const yamlStr = fs.readFileSync(configPath, "utf8"); - const parsedConfig = (load(yamlStr) as FileConfig) || { + const parsedConfig = (parse(yamlStr) as FileConfig) || { http: { routers: {}, services: {} }, }; return parsedConfig; @@ -107,7 +107,7 @@ export const loadOrCreateConfigRemote = async ( if (!stdout) return fileConfig; - const parsedConfig = (load(stdout) as FileConfig) || { + const parsedConfig = (parse(stdout) as FileConfig) || { http: { routers: {}, services: {} }, }; return parsedConfig; @@ -248,7 +248,7 @@ export const writeTraefikConfig = ( try { const { DYNAMIC_TRAEFIK_PATH } = paths(); const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); - const yamlStr = dump(traefikConfig); + const yamlStr = stringify(traefikConfig); fs.writeFileSync(configPath, yamlStr, "utf8"); } catch (e) { console.error("Error saving the YAML config file:", e); @@ -263,7 +263,7 @@ export const writeTraefikConfigRemote = async ( try { const { DYNAMIC_TRAEFIK_PATH } = paths(true); const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); - const yamlStr = dump(traefikConfig); + const yamlStr = stringify(traefikConfig); await execAsyncRemote(serverId, `echo '${yamlStr}' > ${configPath}`); } catch (e) { console.error("Error saving the YAML config file:", e); diff --git a/packages/server/src/utils/traefik/middleware.ts b/packages/server/src/utils/traefik/middleware.ts index 1254e1f51..4897b94ee 100644 --- a/packages/server/src/utils/traefik/middleware.ts +++ b/packages/server/src/utils/traefik/middleware.ts @@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { paths } from "@dokploy/server/constants"; import type { Domain } from "@dokploy/server/services/domain"; -import { dump, load } from "js-yaml"; +import { parse, stringify } from "yaml"; import type { ApplicationNested } from "../builders"; import { execAsyncRemote } from "../process/execAsync"; import { writeTraefikConfigRemote } from "./application"; @@ -76,7 +76,7 @@ export const loadMiddlewares = () => { throw new Error(`File not found: ${configPath}`); } const yamlStr = readFileSync(configPath, "utf8"); - const config = load(yamlStr) as T; + const config = parse(yamlStr) as T; return config; }; @@ -94,7 +94,7 @@ export const loadRemoteMiddlewares = async (serverId: string) => { console.error(`Error: ${stderr}`); throw new Error(`File not found: ${configPath}`); } - const config = load(stdout) as FileConfig; + const config = parse(stdout) as FileConfig; return config; } catch (_) { throw new Error(`File not found: ${configPath}`); @@ -103,7 +103,7 @@ export const loadRemoteMiddlewares = async (serverId: string) => { export const writeMiddleware = (config: T) => { const { DYNAMIC_TRAEFIK_PATH } = paths(); const configPath = join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml"); - const newYamlContent = dump(config); + const newYamlContent = stringify(config); writeFileSync(configPath, newYamlContent, "utf8"); }; diff --git a/packages/server/src/utils/traefik/web-server.ts b/packages/server/src/utils/traefik/web-server.ts index 1534e2f1c..02472a583 100644 --- a/packages/server/src/utils/traefik/web-server.ts +++ b/packages/server/src/utils/traefik/web-server.ts @@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { paths } from "@dokploy/server/constants"; import type { User } from "@dokploy/server/services/user"; -import { dump, load } from "js-yaml"; +import { parse, stringify } from "yaml"; import { loadOrCreateConfig, removeTraefikConfig, @@ -79,13 +79,13 @@ export const updateLetsEncryptEmail = (newEmail: string | null) => { const { MAIN_TRAEFIK_PATH } = paths(); const configPath = join(MAIN_TRAEFIK_PATH, "traefik.yml"); const configContent = readFileSync(configPath, "utf8"); - const config = load(configContent) as MainTraefikConfig; + const config = parse(configContent) as MainTraefikConfig; if (config?.certificatesResolvers?.letsencrypt?.acme) { config.certificatesResolvers.letsencrypt.acme.email = newEmail; } else { throw new Error("Invalid Let's Encrypt configuration structure."); } - const newYamlContent = dump(config); + const newYamlContent = stringify(config); writeFileSync(configPath, newYamlContent, "utf8"); } catch (error) { throw error; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94dedb322..6df6799ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -325,9 +325,6 @@ importers: js-cookie: specifier: ^3.0.5 version: 3.0.5 - js-yaml: - specifier: 4.1.0 - version: 4.1.0 lodash: specifier: 4.17.21 version: 4.17.21 @@ -448,6 +445,9 @@ importers: xterm-addon-fit: specifier: ^0.8.0 version: 0.8.0(xterm@5.3.0) + yaml: + specifier: 2.8.1 + version: 2.8.1 zod: specifier: ^3.25.32 version: 3.25.32 @@ -464,9 +464,6 @@ importers: '@types/js-cookie': specifier: ^3.0.6 version: 3.0.6 - '@types/js-yaml': - specifier: 4.0.9 - version: 4.0.9 '@types/lodash': specifier: 4.17.4 version: 4.17.4 @@ -681,9 +678,6 @@ importers: hi-base32: specifier: ^0.5.1 version: 0.5.1 - js-yaml: - specifier: 4.1.0 - version: 4.1.0 lodash: specifier: 4.17.21 version: 4.17.21 @@ -747,6 +741,9 @@ importers: ws: specifier: 8.16.0 version: 8.16.0 + yaml: + specifier: 2.8.1 + version: 2.8.1 zod: specifier: ^3.25.32 version: 3.25.32 @@ -760,9 +757,6 @@ importers: '@types/dockerode': specifier: 3.3.23 version: 3.3.23 - '@types/js-yaml': - specifier: 4.0.9 - version: 4.0.9 '@types/lodash': specifier: 4.17.4 version: 4.17.4 @@ -3965,9 +3959,6 @@ packages: '@types/js-cookie@3.0.6': resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} - '@types/js-yaml@4.0.9': - resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} - '@types/jsonwebtoken@9.0.9': resolution: {integrity: sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==} @@ -7783,6 +7774,11 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yaml@2.8.1: + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -11223,8 +11219,6 @@ snapshots: '@types/js-cookie@3.0.6': {} - '@types/js-yaml@4.0.9': {} - '@types/jsonwebtoken@9.0.9': dependencies: '@types/ms': 2.1.0 @@ -14032,7 +14026,7 @@ snapshots: postcss-load-config@4.0.2(postcss@8.5.3): dependencies: lilconfig: 3.1.3 - yaml: 2.8.0 + yaml: 2.8.1 optionalDependencies: postcss: 8.5.3 @@ -15353,6 +15347,8 @@ snapshots: yaml@2.8.0: {} + yaml@2.8.1: {} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1