{
+ const ip = data?.server?.ipAddress || serverIp;
+ if (ip) {
+ copy(ip);
+ toast.success("IP Address Copied!");
+ }
+ }}
variant={
!data?.serverId
? "default"
diff --git a/apps/dokploy/scripts/migrate-auth-secret.ts b/apps/dokploy/scripts/migrate-auth-secret.ts
index 5a71678d9a..302612c6d8 100644
--- a/apps/dokploy/scripts/migrate-auth-secret.ts
+++ b/apps/dokploy/scripts/migrate-auth-secret.ts
@@ -46,7 +46,7 @@ async function main() {
if (records.length === 0) {
console.log("✅ No 2FA records found, nothing to migrate.");
- return;
+ process.exit(0);
}
console.log(`📦 Found ${records.length} 2FA record(s) to migrate.`);
diff --git a/apps/dokploy/server/api/routers/backup.ts b/apps/dokploy/server/api/routers/backup.ts
index 75bb60f2c0..d6aea97415 100644
--- a/apps/dokploy/server/api/routers/backup.ts
+++ b/apps/dokploy/server/api/routers/backup.ts
@@ -31,6 +31,8 @@ import { findDestinationById } from "@dokploy/server/services/destination";
import { checkServicePermissionAndAccess } from "@dokploy/server/services/permission";
import { runComposeBackup } from "@dokploy/server/utils/backups/compose";
import {
+ buildRcloneDestination,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "@dokploy/server/utils/backups/utils";
@@ -479,7 +481,7 @@ export const backupRouter = createTRPCRouter({
}
}
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
+ const bucketPath = getDestinationRoot(destination);
const lastSlashIndex = input.search.lastIndexOf("/");
const baseDir =
@@ -491,7 +493,9 @@ export const backupRouter = createTRPCRouter({
? input.search.slice(lastSlashIndex + 1)
: input.search;
- const searchPath = baseDir ? `${bucketPath}/${baseDir}` : bucketPath;
+ const searchPath = baseDir
+ ? buildRcloneDestination(bucketPath, baseDir)
+ : bucketPath;
const listCommand = `rclone lsjson ${rcloneFlags.join(" ")} "${searchPath}" --no-mimetype --no-modtime 2>/dev/null`;
let stdout = "";
diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts
index 2548184781..d1fbb14d3a 100644
--- a/apps/dokploy/server/api/routers/compose.ts
+++ b/apps/dokploy/server/api/routers/compose.ts
@@ -862,6 +862,76 @@ export const composeRouter = createTRPCRouter({
}
}),
+ previewTemplate: protectedProcedure
+ .input(
+ z.object({
+ base64: z.string(),
+ appName: z.string(),
+ serverId: z.string().optional(),
+ }),
+ )
+ .mutation(async ({ input, ctx }) => {
+ try {
+ if (input.serverId) {
+ const accessibleIds = await getAccessibleServerIds(ctx.session);
+ if (!accessibleIds.has(input.serverId)) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not authorized to access this server",
+ });
+ }
+ }
+
+ const decodedData = Buffer.from(input.base64, "base64").toString(
+ "utf-8",
+ );
+
+ let serverIp = "127.0.0.1";
+
+ if (input.serverId) {
+ const server = await findServerById(input.serverId);
+ serverIp = server.ipAddress;
+ } else if (process.env.NODE_ENV !== "development") {
+ const settings = await getWebServerSettings();
+ serverIp = settings?.serverIp || "127.0.0.1";
+ }
+
+ const templateData = JSON.parse(decodedData);
+ const config = parse(templateData.config) as CompleteTemplate;
+
+ if (!templateData.compose || !config) {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message:
+ "Invalid template format. Must contain compose and config fields",
+ });
+ }
+
+ const configModified = {
+ ...config,
+ variables: {
+ APP_NAME: input.appName,
+ ...config.variables,
+ },
+ };
+
+ const processedTemplate = processTemplate(configModified, {
+ serverIp,
+ projectName: input.appName,
+ });
+
+ return {
+ compose: templateData.compose,
+ template: processedTemplate,
+ };
+ } catch (error) {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message: `Error processing template: ${error instanceof Error ? error.message : error}`,
+ });
+ }
+ }),
+
import: protectedProcedure
.input(
z.object({
diff --git a/apps/dokploy/server/api/routers/deployment.ts b/apps/dokploy/server/api/routers/deployment.ts
index 6f3b1d1ae7..d17a04dfb6 100644
--- a/apps/dokploy/server/api/routers/deployment.ts
+++ b/apps/dokploy/server/api/routers/deployment.ts
@@ -151,6 +151,14 @@ export const deploymentRouter = createTRPCRouter({
await checkServicePermissionAndAccess(ctx, serviceId, {
deployment: ["cancel"],
});
+ } else if (deployment.schedule?.serverId) {
+ const targetServer = await findServerById(deployment.schedule.serverId);
+ if (targetServer.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You don't have access to this deployment.",
+ });
+ }
}
if (!deployment.pid) {
@@ -188,6 +196,14 @@ export const deploymentRouter = createTRPCRouter({
await checkServicePermissionAndAccess(ctx, serviceId, {
deployment: ["cancel"],
});
+ } else if (deployment.schedule?.serverId) {
+ const targetServer = await findServerById(deployment.schedule.serverId);
+ if (targetServer.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You don't have access to this deployment.",
+ });
+ }
}
const result = await removeDeployment(input.deploymentId);
await audit(ctx, {
@@ -197,4 +213,47 @@ export const deploymentRouter = createTRPCRouter({
});
return result;
}),
+
+ readLogs: protectedProcedure
+ .input(
+ z.object({
+ deploymentId: z.string().min(1),
+ tail: z.number().int().min(1).max(10000).default(100),
+ }),
+ )
+ .query(async ({ input, ctx }) => {
+ const deployment = await findDeploymentById(input.deploymentId);
+ const serviceId = deployment.applicationId || deployment.composeId;
+ if (serviceId) {
+ await checkServicePermissionAndAccess(ctx, serviceId, {
+ deployment: ["read"],
+ });
+ } else if (deployment.schedule?.serverId) {
+ const targetServer = await findServerById(deployment.schedule.serverId);
+ if (targetServer.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You don't have access to this deployment.",
+ });
+ }
+ }
+
+ if (!deployment.logPath) {
+ return "";
+ }
+
+ const command = `tail -n ${input.tail} "${deployment.logPath}" 2>/dev/null || echo ""`;
+ const serverId = deployment.serverId || deployment.schedule?.serverId;
+ if (serverId) {
+ const { stdout } = await execAsyncRemote(serverId, command);
+ return stdout;
+ }
+
+ if (IS_CLOUD) {
+ return "";
+ }
+
+ const { stdout } = await execAsync(command);
+ return stdout;
+ }),
});
diff --git a/apps/dokploy/server/api/routers/destination.ts b/apps/dokploy/server/api/routers/destination.ts
index cf7395a3f7..1552304ba8 100644
--- a/apps/dokploy/server/api/routers/destination.ts
+++ b/apps/dokploy/server/api/routers/destination.ts
@@ -8,6 +8,7 @@ import {
updateDestinationById,
} from "@dokploy/server";
import { db } from "@dokploy/server/db";
+import { CUSTOM_DESTINATION_PROVIDER } from "@dokploy/server/db/validations/destination";
import { TRPCError } from "@trpc/server";
import { desc, eq } from "drizzle-orm";
import { createTRPCRouter, withPermission } from "@/server/api/trpc";
@@ -17,7 +18,9 @@ import {
apiFindOneDestination,
apiRemoveDestination,
apiUpdateDestination,
+ buildRcloneDestination,
destinations,
+ getDestinationRoot,
} from "@/server/db/schema";
export const destinationRouter = createTRPCRouter({
@@ -57,25 +60,32 @@ export const destinationRouter = createTRPCRouter({
additionalFlags,
} = input;
try {
- const rcloneFlags = [
- `--s3-access-key-id="${accessKey}"`,
- `--s3-secret-access-key="${secretAccessKey}"`,
- `--s3-region="${region}"`,
- `--s3-endpoint="${endpoint}"`,
- "--s3-no-check-bucket",
- "--s3-force-path-style",
- "--retries 1",
- "--low-level-retries 1",
- "--timeout 10s",
- "--contimeout 5s",
- ];
- if (provider) {
+ const isCustomDestination = provider === CUSTOM_DESTINATION_PROVIDER;
+ const rcloneFlags = isCustomDestination
+ ? [...(additionalFlags ?? []), "--retries 1", "--low-level-retries 1"]
+ : [
+ `--s3-access-key-id="${accessKey}"`,
+ `--s3-secret-access-key="${secretAccessKey}"`,
+ `--s3-region="${region}"`,
+ `--s3-endpoint="${endpoint}"`,
+ "--s3-no-check-bucket",
+ "--s3-force-path-style",
+ "--retries 1",
+ "--low-level-retries 1",
+ "--timeout 10s",
+ "--contimeout 5s",
+ ];
+ if (!isCustomDestination && provider) {
rcloneFlags.unshift(`--s3-provider="${provider}"`);
}
- if (additionalFlags?.length) {
+ if (!isCustomDestination && additionalFlags?.length) {
rcloneFlags.push(...additionalFlags);
}
- const rcloneDestination = `:s3:${bucket}`;
+ const destinationRoot = getDestinationRoot(input);
+ const rcloneDestination = buildRcloneDestination(
+ destinationRoot,
+ bucket,
+ );
const rcloneCommand = `rclone ls ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
if (IS_CLOUD && !input.serverId) {
diff --git a/apps/dokploy/server/api/routers/organization.ts b/apps/dokploy/server/api/routers/organization.ts
index 51c1fec5d9..6af018ed81 100644
--- a/apps/dokploy/server/api/routers/organization.ts
+++ b/apps/dokploy/server/api/routers/organization.ts
@@ -295,6 +295,14 @@ export const organizationRouter = createTRPCRouter({
});
}
+ // Owner role is non-delegable — no one can invite as owner
+ if (input.role === "owner") {
+ throw new TRPCError({
+ code: "FORBIDDEN",
+ message: "Cannot invite a user with the owner role",
+ });
+ }
+
// If assigning a custom role, verify it exists
if (!["owner", "admin", "member"].includes(input.role)) {
const customRole = await db.query.organizationRole.findFirst({
diff --git a/apps/dokploy/server/api/routers/user.ts b/apps/dokploy/server/api/routers/user.ts
index 93b7e6cf62..fc3b29d6e4 100644
--- a/apps/dokploy/server/api/routers/user.ts
+++ b/apps/dokploy/server/api/routers/user.ts
@@ -23,6 +23,7 @@ import {
apiUpdateUser,
invitation,
member,
+ session,
user,
} from "@dokploy/server/db/schema";
import {
@@ -32,7 +33,7 @@ import {
import { hasValidLicense } from "@dokploy/server/services/proprietary/license-key";
import { TRPCError } from "@trpc/server";
import * as bcrypt from "bcrypt";
-import { and, asc, eq, gt } from "drizzle-orm";
+import { and, asc, eq, gt, ne } from "drizzle-orm";
import { z } from "zod";
import { audit } from "@/server/api/utils/audit";
import {
@@ -229,6 +230,15 @@ export const userRouter = createTRPCRouter({
password: bcrypt.hashSync(input.password, 10),
})
.where(eq(account.userId, ctx.user.id));
+
+ await db
+ .delete(session)
+ .where(
+ and(
+ eq(session.userId, ctx.user.id),
+ ne(session.id, ctx.session.id),
+ ),
+ );
}
try {
@@ -594,6 +604,13 @@ export const userRouter = createTRPCRouter({
});
}
+ if (input.role === "owner") {
+ throw new TRPCError({
+ code: "FORBIDDEN",
+ message: "Cannot create a user with the owner role",
+ });
+ }
+
return await createOrganizationUserWithCredentials({
organizationId: ctx.session.activeOrganizationId,
email: input.email,
diff --git a/packages/server/src/db/schema/destination.ts b/packages/server/src/db/schema/destination.ts
index c479679fe3..c29c6e7adb 100644
--- a/packages/server/src/db/schema/destination.ts
+++ b/packages/server/src/db/schema/destination.ts
@@ -6,6 +6,7 @@ import { z } from "zod";
import {
ADDITIONAL_FLAG_ERROR,
ADDITIONAL_FLAG_REGEX,
+ CUSTOM_DESTINATION_PROVIDER,
} from "../validations/destination";
import { organization } from "./account";
import { backups } from "./backups";
@@ -54,7 +55,67 @@ const createSchema = createInsertSchema(destinations, {
.default([]),
});
-export const apiCreateDestination = createSchema
+const validateDestination = <
+ T extends {
+ provider?: string | null;
+ accessKey: string;
+ secretAccessKey: string;
+ region: string;
+ bucket: string;
+ endpoint: string;
+ },
+>(
+ data: T,
+ ctx: z.RefinementCtx,
+) => {
+ const isCustomDestination = data.provider === CUSTOM_DESTINATION_PROVIDER;
+
+ if (isCustomDestination) {
+ if (!data.endpoint.trim()) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: "Remote root is required for custom destinations",
+ path: ["endpoint"],
+ });
+ }
+
+ if (!data.bucket.trim()) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: "Destination path is required for custom destinations",
+ path: ["bucket"],
+ });
+ }
+
+ return;
+ }
+
+ if (!data.accessKey.trim()) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: "Access Key Id is required",
+ path: ["accessKey"],
+ });
+ }
+
+ if (!data.secretAccessKey.trim()) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: "Secret Access Key is required",
+ path: ["secretAccessKey"],
+ });
+ }
+
+ if (!data.region.trim()) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: "Region is required",
+ path: ["region"],
+ });
+ }
+};
+
+const destinationInputSchema = createSchema
.pick({
name: true,
provider: true,
@@ -68,7 +129,10 @@ export const apiCreateDestination = createSchema
.required()
.extend({
serverId: z.string().optional(),
- });
+ })
+ .superRefine(validateDestination);
+
+export const apiCreateDestination = destinationInputSchema;
export const apiFindOneDestination = z.object({
destinationId: z.string().min(1),
@@ -95,4 +159,5 @@ export const apiUpdateDestination = createSchema
.required()
.extend({
serverId: z.string().optional(),
- });
+ })
+ .superRefine(validateDestination);
diff --git a/packages/server/src/db/schema/registry.ts b/packages/server/src/db/schema/registry.ts
index 68db88f802..02b2f4c558 100644
--- a/packages/server/src/db/schema/registry.ts
+++ b/packages/server/src/db/schema/registry.ts
@@ -44,6 +44,13 @@ export const registryRelations = relations(registry, ({ many }) => ({
}),
}));
+// Image references require a lowercase namespace (e.g. Docker Hub username).
+const registryUsernameSchema = z
+ .string()
+ .trim()
+ .min(1)
+ .transform((s) => s.toLowerCase());
+
// Registry URLs must be hostname[:port] only — no shell metacharacters
// Empty string is allowed (means default/Docker Hub registry)
const registryUrlSchema = z
@@ -57,7 +64,7 @@ const registryUrlSchema = z
const createSchema = createInsertSchema(registry, {
registryName: z.string().min(1),
- username: z.string().min(1),
+ username: registryUsernameSchema,
password: z.string().min(1),
registryUrl: registryUrlSchema,
organizationId: z.string().min(1),
@@ -70,7 +77,7 @@ export const apiCreateRegistry = createSchema
.pick({})
.extend({
registryName: z.string().min(1),
- username: z.string().min(1),
+ username: registryUsernameSchema,
password: z.string().min(1),
registryUrl: registryUrlSchema,
registryType: z.enum(["cloud"]),
@@ -83,7 +90,7 @@ export const apiCreateRegistry = createSchema
export const apiTestRegistry = createSchema.pick({}).extend({
registryName: z.string().optional(),
- username: z.string().min(1),
+ username: registryUsernameSchema,
password: z.string().min(1),
registryUrl: registryUrlSchema,
registryType: z.enum(["cloud"]),
diff --git a/packages/server/src/db/validations/destination.ts b/packages/server/src/db/validations/destination.ts
index d342646b4a..23e92a0c6e 100644
--- a/packages/server/src/db/validations/destination.ts
+++ b/packages/server/src/db/validations/destination.ts
@@ -1,3 +1,4 @@
export const ADDITIONAL_FLAG_REGEX = /^--[a-zA-Z0-9-]+(=[a-zA-Z0-9._:/@-]+)?$/;
export const ADDITIONAL_FLAG_ERROR =
"Invalid flag format. Must start with -- (e.g. --s3-sign-accept-encoding=false)";
+export const CUSTOM_DESTINATION_PROVIDER = "Custom";
diff --git a/packages/server/src/utils/backups/compose.ts b/packages/server/src/utils/backups/compose.ts
index 6640590b03..c3de3314e5 100644
--- a/packages/server/src/utils/backups/compose.ts
+++ b/packages/server/src/utils/backups/compose.ts
@@ -9,8 +9,10 @@ import { findProjectById } from "@dokploy/server/services/project";
import { sendDatabaseBackupNotifications } from "../notifications/database-backup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import {
+ buildRcloneDestination,
getBackupCommand,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "./utils";
@@ -35,7 +37,10 @@ export const runComposeBackup = async (
try {
const rcloneFlags = getS3Credentials(destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const rcloneCommand = `rclone rcat ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
const backupCommand = getBackupCommand(
diff --git a/packages/server/src/utils/backups/index.ts b/packages/server/src/utils/backups/index.ts
index 876579cb12..9f00351bec 100644
--- a/packages/server/src/utils/backups/index.ts
+++ b/packages/server/src/utils/backups/index.ts
@@ -10,7 +10,13 @@ import { startLogCleanup } from "../access-log/handler";
import { cleanupAll } from "../docker/utils";
import { sendDockerCleanupNotifications } from "../notifications/docker-cleanup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
-import { getS3Credentials, normalizeS3Path, scheduleBackup } from "./utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+ normalizeS3Path,
+ scheduleBackup,
+} from "./utils";
export const initCronJobs = async () => {
console.log("Setting up cron jobs....");
@@ -133,7 +139,10 @@ export const keepLatestNBackups = async (
try {
const rcloneFlags = getS3Credentials(backup.destination);
const appName = getServiceAppName(backup);
- const backupFilesPath = `:s3:${backup.destination.bucket}/${appName}/${normalizeS3Path(backup.prefix)}`;
+ const backupFilesPath = buildRcloneDestination(
+ getDestinationRoot(backup.destination),
+ `${appName}/${normalizeS3Path(backup.prefix)}`,
+ );
// --include "*.bson.gz" or "*.sql.gz" or "*.zip" ensures nothing else other than the dokploy backup files are touched by rclone
const rcloneList = `rclone lsf ${rcloneFlags.join(" ")} --include "*${backup.databaseType === "web-server" ? ".zip" : ".{sql.gz,bson.gz}"}" ${backupFilesPath}`;
diff --git a/packages/server/src/utils/backups/libsql.ts b/packages/server/src/utils/backups/libsql.ts
index a994db8bd6..5aa3e82fc1 100644
--- a/packages/server/src/utils/backups/libsql.ts
+++ b/packages/server/src/utils/backups/libsql.ts
@@ -9,8 +9,10 @@ import { findProjectById } from "@dokploy/server/services/project";
import { sendDatabaseBackupNotifications } from "../notifications/database-backup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import {
+ buildRcloneDestination,
getBackupCommand,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "./utils";
@@ -34,7 +36,10 @@ export const runLibsqlBackup = async (
const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`;
try {
const rcloneFlags = getS3Credentials(destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const rcloneCommand = `rclone rcat ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
diff --git a/packages/server/src/utils/backups/mariadb.ts b/packages/server/src/utils/backups/mariadb.ts
index dea22ff189..a0bde84521 100644
--- a/packages/server/src/utils/backups/mariadb.ts
+++ b/packages/server/src/utils/backups/mariadb.ts
@@ -9,8 +9,10 @@ import { findProjectById } from "@dokploy/server/services/project";
import { sendDatabaseBackupNotifications } from "../notifications/database-backup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import {
+ buildRcloneDestination,
getBackupCommand,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "./utils";
@@ -33,7 +35,10 @@ export const runMariadbBackup = async (
});
try {
const rcloneFlags = getS3Credentials(destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const rcloneCommand = `rclone rcat ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
const backupCommand = getBackupCommand(
diff --git a/packages/server/src/utils/backups/mongo.ts b/packages/server/src/utils/backups/mongo.ts
index cebece14f7..f9212fcce5 100644
--- a/packages/server/src/utils/backups/mongo.ts
+++ b/packages/server/src/utils/backups/mongo.ts
@@ -9,8 +9,10 @@ import { findProjectById } from "@dokploy/server/services/project";
import { sendDatabaseBackupNotifications } from "../notifications/database-backup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import {
+ buildRcloneDestination,
getBackupCommand,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "./utils";
@@ -30,7 +32,10 @@ export const runMongoBackup = async (mongo: Mongo, backup: BackupSchedule) => {
});
try {
const rcloneFlags = getS3Credentials(destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const rcloneCommand = `rclone rcat ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
const backupCommand = getBackupCommand(
diff --git a/packages/server/src/utils/backups/mysql.ts b/packages/server/src/utils/backups/mysql.ts
index a72f598806..42a891c515 100644
--- a/packages/server/src/utils/backups/mysql.ts
+++ b/packages/server/src/utils/backups/mysql.ts
@@ -9,8 +9,10 @@ import { findProjectById } from "@dokploy/server/services/project";
import { sendDatabaseBackupNotifications } from "../notifications/database-backup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import {
+ buildRcloneDestination,
getBackupCommand,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "./utils";
@@ -31,7 +33,10 @@ export const runMySqlBackup = async (mysql: MySql, backup: BackupSchedule) => {
try {
const rcloneFlags = getS3Credentials(destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const rcloneCommand = `rclone rcat ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
diff --git a/packages/server/src/utils/backups/postgres.ts b/packages/server/src/utils/backups/postgres.ts
index 30a88db2b3..224495b33a 100644
--- a/packages/server/src/utils/backups/postgres.ts
+++ b/packages/server/src/utils/backups/postgres.ts
@@ -9,8 +9,10 @@ import { findProjectById } from "@dokploy/server/services/project";
import { sendDatabaseBackupNotifications } from "../notifications/database-backup";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import {
+ buildRcloneDestination,
getBackupCommand,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "./utils";
@@ -34,7 +36,10 @@ export const runPostgresBackup = async (
const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`;
try {
const rcloneFlags = getS3Credentials(destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const rcloneCommand = `rclone rcat ${rcloneFlags.join(" ")} "${rcloneDestination}"`;
diff --git a/packages/server/src/utils/backups/utils.ts b/packages/server/src/utils/backups/utils.ts
index 365ebff415..6dad9cf3f2 100644
--- a/packages/server/src/utils/backups/utils.ts
+++ b/packages/server/src/utils/backups/utils.ts
@@ -1,6 +1,5 @@
import { logger } from "@dokploy/server/lib/logger";
import type { BackupSchedule } from "@dokploy/server/services/backup";
-import type { Destination } from "@dokploy/server/services/destination";
import { scheduledJobs, scheduleJob } from "node-schedule";
import { keepLatestNBackups } from ".";
import { runComposeBackup } from "./compose";
@@ -11,6 +10,16 @@ import { runMySqlBackup } from "./mysql";
import { runPostgresBackup } from "./postgres";
import { runWebServerBackup } from "./web-server";
+export type RcloneDestinationConfig = {
+ provider?: string | null;
+ accessKey?: string | null;
+ secretAccessKey?: string | null;
+ bucket: string;
+ region?: string | null;
+ endpoint: string;
+ additionalFlags?: string[] | null;
+};
+
export const scheduleBackup = (backup: BackupSchedule) => {
const {
schedule,
@@ -66,7 +75,49 @@ export const normalizeS3Path = (prefix: string) => {
return normalizedPrefix ? `${normalizedPrefix}/` : "";
};
-export const getS3Credentials = (destination: Destination) => {
+export const CUSTOM_DESTINATION_PROVIDER = "Custom";
+
+export const isCustomDestination = (destination: RcloneDestinationConfig) =>
+ destination.provider === CUSTOM_DESTINATION_PROVIDER;
+
+export const getDestinationRoot = (destination: RcloneDestinationConfig) => {
+ if (isCustomDestination(destination)) {
+ const endpoint = destination.endpoint.trim();
+ if (!endpoint) {
+ throw new Error("Custom destinations require a remote root");
+ }
+ return endpoint;
+ }
+
+ return `:s3:${destination.bucket}`;
+};
+
+export const buildRcloneDestination = (root: string, relativePath: string) => {
+ const normalizedRoot = root.trim();
+ const normalizedRelativePath = relativePath.replace(/^\/+/, "");
+
+ if (!normalizedRelativePath) {
+ return normalizedRoot;
+ }
+
+ if (normalizedRoot.endsWith(":") || normalizedRoot.endsWith("/")) {
+ return `${normalizedRoot}${normalizedRelativePath}`;
+ }
+
+ return `${normalizedRoot}/${normalizedRelativePath}`;
+};
+
+export const joinRclonePath = (root: string, relativePath: string) => {
+ return buildRcloneDestination(root, relativePath);
+};
+
+export const getS3Credentials = (destination: RcloneDestinationConfig) => {
+ if (isCustomDestination(destination)) {
+ return destination.additionalFlags?.length
+ ? destination.additionalFlags
+ : [];
+ }
+
const { accessKey, secretAccessKey, region, endpoint, provider } =
destination;
const rcloneFlags = [
diff --git a/packages/server/src/utils/backups/web-server.ts b/packages/server/src/utils/backups/web-server.ts
index 712cc08090..0285fe132c 100644
--- a/packages/server/src/utils/backups/web-server.ts
+++ b/packages/server/src/utils/backups/web-server.ts
@@ -11,7 +11,13 @@ import {
import { findDestinationById } from "@dokploy/server/services/destination";
import { sendDokployBackupNotifications } from "../notifications/dokploy-backup";
import { execAsync } from "../process/execAsync";
-import { getBackupTimestamp, getS3Credentials, normalizeS3Path } from "./utils";
+import {
+ buildRcloneDestination,
+ getBackupTimestamp,
+ getDestinationRoot,
+ getS3Credentials,
+ normalizeS3Path,
+} from "./utils";
function formatBytes(bytes?: number) {
if (bytes === undefined) return "Unknown size";
@@ -41,7 +47,10 @@ export const runWebServerBackup = async (backup: BackupSchedule) => {
const { BASE_PATH } = paths();
const tempDir = await mkdtemp(join(tmpdir(), "dokploy-backup-"));
const backupFileName = `webserver-backup-${timestamp}.zip`;
- const s3Path = `:s3:${destination.bucket}/${backup.appName}/${normalizeS3Path(backup.prefix)}${backupFileName}`;
+ const s3Path = buildRcloneDestination(
+ getDestinationRoot(destination),
+ `${backup.appName}/${normalizeS3Path(backup.prefix)}${backupFileName}`,
+ );
try {
await execAsync(`mkdir -p ${tempDir}/filesystem`);
diff --git a/packages/server/src/utils/cluster/upload.ts b/packages/server/src/utils/cluster/upload.ts
index aa014a05c8..6bf02547c9 100644
--- a/packages/server/src/utils/cluster/upload.ts
+++ b/packages/server/src/utils/cluster/upload.ts
@@ -101,8 +101,8 @@ export const getRegistryTag = (registry: Registry, imageName: string) => {
// Extract the repository name (last part after '/')
const repositoryName = extractRepositoryName(imageName);
- // Build the final tag using registry's username/prefix
- const targetPrefix = imagePrefix || username;
+ // Build the final tag using registry's username/prefix (must be lowercase for valid image refs)
+ const targetPrefix = (imagePrefix || username).toLowerCase();
const finalRegistry = registryUrl || "";
return finalRegistry
diff --git a/packages/server/src/utils/docker/domain.ts b/packages/server/src/utils/docker/domain.ts
index 1a6e77a287..8094f1df2a 100644
--- a/packages/server/src/utils/docker/domain.ts
+++ b/packages/server/src/utils/docker/domain.ts
@@ -337,6 +337,10 @@ export const createDomainLabels = (
labels.push(
`traefik.http.routers.${routerName}.tls.certresolver=${customCertResolver}`,
);
+ } else if (certificateType === "none" && https) {
+ // No cert resolver, but HTTPS is enabled (default/custom certificate):
+ // explicitly enable TLS so Traefik serves the router over HTTPS.
+ labels.push(`traefik.http.routers.${routerName}.tls=true`);
}
}
diff --git a/packages/server/src/utils/restore/compose.ts b/packages/server/src/utils/restore/compose.ts
index 20cac27fb4..76b555d54b 100644
--- a/packages/server/src/utils/restore/compose.ts
+++ b/packages/server/src/utils/restore/compose.ts
@@ -2,7 +2,11 @@ import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Compose } from "@dokploy/server/services/compose";
import type { Destination } from "@dokploy/server/services/destination";
import type { z } from "zod";
-import { getS3Credentials } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+} from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getRestoreCommand } from "./utils";
@@ -24,8 +28,10 @@ export const restoreComposeBackup = async (
const { serverId, appName, composeType } = compose;
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
- const backupPath = `${bucketPath}/${backupInput.backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupInput.backupFile,
+ );
let rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip`;
if (backupInput.metadata?.mongo) {
diff --git a/packages/server/src/utils/restore/libsql.ts b/packages/server/src/utils/restore/libsql.ts
index e984826f84..01ca1e6534 100644
--- a/packages/server/src/utils/restore/libsql.ts
+++ b/packages/server/src/utils/restore/libsql.ts
@@ -2,7 +2,12 @@ import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Destination } from "@dokploy/server/services/destination";
import type { Libsql } from "@dokploy/server/services/libsql";
import type { z } from "zod";
-import { getS3Credentials, getServiceContainerCommand } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+ getServiceContainerCommand,
+} from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
export const restoreLibsqlBackup = async (
@@ -15,9 +20,10 @@ export const restoreLibsqlBackup = async (
const { appName, serverId } = libsql;
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
-
- const backupPath = `${bucketPath}/${backupInput.backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupInput.backupFile,
+ );
const rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} "${backupPath}"`;
diff --git a/packages/server/src/utils/restore/mariadb.ts b/packages/server/src/utils/restore/mariadb.ts
index ffbceba765..d71c86cdde 100644
--- a/packages/server/src/utils/restore/mariadb.ts
+++ b/packages/server/src/utils/restore/mariadb.ts
@@ -2,7 +2,11 @@ import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Destination } from "@dokploy/server/services/destination";
import type { Mariadb } from "@dokploy/server/services/mariadb";
import type { z } from "zod";
-import { getS3Credentials } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+} from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getRestoreCommand } from "./utils";
@@ -16,8 +20,10 @@ export const restoreMariadbBackup = async (
const { appName, serverId, databaseUser, databasePassword } = mariadb;
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
- const backupPath = `${bucketPath}/${backupInput.backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupInput.backupFile,
+ );
const rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip`;
diff --git a/packages/server/src/utils/restore/mongo.ts b/packages/server/src/utils/restore/mongo.ts
index 4329a49857..2e669635bc 100644
--- a/packages/server/src/utils/restore/mongo.ts
+++ b/packages/server/src/utils/restore/mongo.ts
@@ -2,7 +2,11 @@ import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Destination } from "@dokploy/server/services/destination";
import type { Mongo } from "@dokploy/server/services/mongo";
import type { z } from "zod";
-import { getS3Credentials } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+} from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getRestoreCommand } from "./utils";
@@ -16,8 +20,10 @@ export const restoreMongoBackup = async (
const { appName, databasePassword, databaseUser, serverId } = mongo;
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
- const backupPath = `${bucketPath}/${backupInput.backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupInput.backupFile,
+ );
const rcloneCommand = `rclone copy ${rcloneFlags.join(" ")} "${backupPath}"`;
const command = getRestoreCommand({
diff --git a/packages/server/src/utils/restore/mysql.ts b/packages/server/src/utils/restore/mysql.ts
index f5187242cf..fa36c62996 100644
--- a/packages/server/src/utils/restore/mysql.ts
+++ b/packages/server/src/utils/restore/mysql.ts
@@ -2,7 +2,11 @@ import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Destination } from "@dokploy/server/services/destination";
import type { MySql } from "@dokploy/server/services/mysql";
import type { z } from "zod";
-import { getS3Credentials } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+} from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getRestoreCommand } from "./utils";
@@ -16,8 +20,10 @@ export const restoreMySqlBackup = async (
const { appName, databaseRootPassword, serverId } = mysql;
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
- const backupPath = `${bucketPath}/${backupInput.backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupInput.backupFile,
+ );
const rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip`;
diff --git a/packages/server/src/utils/restore/postgres.ts b/packages/server/src/utils/restore/postgres.ts
index 19f32989f0..ad49be5d41 100644
--- a/packages/server/src/utils/restore/postgres.ts
+++ b/packages/server/src/utils/restore/postgres.ts
@@ -2,7 +2,11 @@ import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Destination } from "@dokploy/server/services/destination";
import type { Postgres } from "@dokploy/server/services/postgres";
import type { z } from "zod";
-import { getS3Credentials } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+} from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getRestoreCommand } from "./utils";
@@ -16,9 +20,10 @@ export const restorePostgresBackup = async (
const { appName, databaseUser, serverId } = postgres;
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
-
- const backupPath = `${bucketPath}/${backupInput.backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupInput.backupFile,
+ );
const rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip`;
diff --git a/packages/server/src/utils/restore/web-server.ts b/packages/server/src/utils/restore/web-server.ts
index 683a1898ae..d664486513 100644
--- a/packages/server/src/utils/restore/web-server.ts
+++ b/packages/server/src/utils/restore/web-server.ts
@@ -3,7 +3,11 @@ import { tmpdir } from "node:os";
import { join } from "node:path";
import { IS_CLOUD, paths } from "@dokploy/server/constants";
import type { Destination } from "@dokploy/server/services/destination";
-import { getS3Credentials } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+} from "../backups/utils";
import { execAsync } from "../process/execAsync";
export const restoreWebServerBackup = async (
@@ -16,8 +20,10 @@ export const restoreWebServerBackup = async (
}
try {
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
- const backupPath = `${bucketPath}/${backupFile}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupFile,
+ );
const { BASE_PATH } = paths();
// Create a temporary directory outside of BASE_PATH
@@ -32,8 +38,8 @@ export const restoreWebServerBackup = async (
emit("Creating temporary directory...");
await execAsync(`mkdir -p ${tempDir}`);
- // Download backup from S3
- emit("Downloading backup from S3...");
+ // Download backup from the configured remote
+ emit("Downloading backup from the configured remote...");
await execAsync(
`rclone copyto ${rcloneFlags.join(" ")} "${backupPath}" "${tempDir}/${backupFile}"`,
);
diff --git a/packages/server/src/utils/volume-backups/backup.ts b/packages/server/src/utils/volume-backups/backup.ts
index 1d795a14a0..b3c50d6a1c 100644
--- a/packages/server/src/utils/volume-backups/backup.ts
+++ b/packages/server/src/utils/volume-backups/backup.ts
@@ -3,7 +3,9 @@ import { paths } from "@dokploy/server/constants";
import { findComposeById } from "@dokploy/server/services/compose";
import type { findVolumeBackupById } from "@dokploy/server/services/volume-backups";
import {
+ buildRcloneDestination,
getBackupTimestamp,
+ getDestinationRoot,
getS3Credentials,
normalizeS3Path,
} from "../backups/utils";
@@ -39,7 +41,10 @@ export const backupVolume = async (
const backupFileName = `${volumeName}-${getBackupTimestamp()}.tar`;
const bucketDestination = `${s3AppName}/${normalizeS3Path(prefix || "")}${backupFileName}`;
const rcloneFlags = getS3Credentials(volumeBackup.destination);
- const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`;
+ const rcloneDestination = buildRcloneDestination(
+ getDestinationRoot(destination),
+ bucketDestination,
+ );
const volumeBackupPath = path.join(VOLUME_BACKUPS_PATH, volumeBackup.appName);
const rcloneCommand = `rclone copyto ${rcloneFlags.join(" ")} "${volumeBackupPath}/${backupFileName}" "${rcloneDestination}"`;
diff --git a/packages/server/src/utils/volume-backups/restore.ts b/packages/server/src/utils/volume-backups/restore.ts
index 6f6068cafc..f8c4907c31 100644
--- a/packages/server/src/utils/volume-backups/restore.ts
+++ b/packages/server/src/utils/volume-backups/restore.ts
@@ -3,7 +3,9 @@ import {
findApplicationById,
findComposeById,
findDestinationById,
+ buildRcloneDestination,
getS3Credentials,
+ getDestinationRoot,
paths,
} from "../..";
@@ -19,10 +21,12 @@ export const restoreVolume = async (
const { VOLUME_BACKUPS_PATH } = paths(!!serverId);
const volumeBackupPath = path.join(VOLUME_BACKUPS_PATH, volumeName);
const rcloneFlags = getS3Credentials(destination);
- const bucketPath = `:s3:${destination.bucket}`;
- const backupPath = `${bucketPath}/${backupFileName}`;
+ const backupPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ backupFileName,
+ );
- // Command to download backup file from S3
+ // Command to download backup file from the configured remote
const downloadCommand = `rclone copyto ${rcloneFlags.join(" ")} "${backupPath}" "${volumeBackupPath}/${backupFileName}"`;
// Base restore command that creates the volume and restores data
@@ -31,7 +35,7 @@ export const restoreVolume = async (
echo "Volume name: ${volumeName}"
echo "Backup file name: ${backupFileName}"
echo "Volume backup path: ${volumeBackupPath}"
- echo "Downloading backup from S3..."
+ echo "Downloading backup from the configured remote..."
mkdir -p ${volumeBackupPath}
${downloadCommand}
echo "Download completed ✅"
diff --git a/packages/server/src/utils/volume-backups/utils.ts b/packages/server/src/utils/volume-backups/utils.ts
index a1eb0a8f1e..27eec4fe88 100644
--- a/packages/server/src/utils/volume-backups/utils.ts
+++ b/packages/server/src/utils/volume-backups/utils.ts
@@ -10,7 +10,12 @@ import {
execAsyncRemote,
} from "@dokploy/server/utils/process/execAsync";
import { scheduledJobs, scheduleJob } from "node-schedule";
-import { getS3Credentials, normalizeS3Path } from "../backups/utils";
+import {
+ buildRcloneDestination,
+ getDestinationRoot,
+ getS3Credentials,
+ normalizeS3Path,
+} from "../backups/utils";
import { sendVolumeBackupNotifications } from "../notifications/volume-backup";
import { backupVolume, getVolumeServiceAppName } from "./backup";
@@ -84,7 +89,10 @@ const cleanupOldVolumeBackups = async (
try {
const rcloneFlags = getS3Credentials(destination);
const s3AppName = getVolumeServiceAppName(volumeBackup);
- const backupFilesPath = `:s3:${destination.bucket}/${s3AppName}/${normalizeS3Path(prefix || "")}`;
+ const backupFilesPath = buildRcloneDestination(
+ getDestinationRoot(destination),
+ `${s3AppName}/${normalizeS3Path(prefix || "")}`,
+ );
const listCommand = `rclone lsf ${rcloneFlags.join(" ")} --include \"${volumeName}-*.tar\" ${backupFilesPath}`;
const sortAndPick = `sort -r | tail -n +$((${keepLatestCount}+1)) | xargs -I{}`;
const deleteCommand = `rclone delete ${rcloneFlags.join(" ")} ${backupFilesPath}{}`;
diff --git a/packages/server/src/utils/watch-paths/should-deploy.ts b/packages/server/src/utils/watch-paths/should-deploy.ts
index 4bc1de1d16..c3e7677fed 100644
--- a/packages/server/src/utils/watch-paths/should-deploy.ts
+++ b/packages/server/src/utils/watch-paths/should-deploy.ts
@@ -2,8 +2,11 @@ import micromatch from "micromatch";
export const shouldDeploy = (
watchPaths: string[] | null,
- modifiedFiles: string[],
+ modifiedFiles: (string | null | undefined)[] | null | undefined,
): boolean => {
if (!watchPaths || watchPaths?.length === 0) return true;
- return micromatch.some(modifiedFiles, watchPaths);
+ const files = (modifiedFiles ?? []).filter(
+ (file): file is string => typeof file === "string",
+ );
+ return micromatch.some(files, watchPaths);
};
diff --git a/packages/server/src/wss/utils.ts b/packages/server/src/wss/utils.ts
index bce5aa245a..ec590399d3 100644
--- a/packages/server/src/wss/utils.ts
+++ b/packages/server/src/wss/utils.ts
@@ -40,7 +40,7 @@ export const readValidDirectory = (
directory: string,
serverId?: string | null,
) => {
- if (!/^[\w/. :-]{1,500}$/.test(directory)) {
+ if (!/^[\w/. :[\]-]{1,500}$/.test(directory)) {
return false;
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 55f10de341..41c8a66be2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -51,7 +51,7 @@ importers:
version: 4.12.2
inngest:
specifier: 3.40.1
- version: 3.40.1(encoding@0.1.13)(h3@1.15.1)(hono@4.12.2)(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(typescript@5.9.3)
+ version: 3.40.1(encoding@0.1.13)(h3@1.15.1)(hono@4.12.2)(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(typescript@5.9.3)
pino:
specifier: 9.4.0
version: 9.4.0
@@ -115,10 +115,10 @@ importers:
version: 2.0.30(zod@4.3.6)
'@better-auth/api-key':
specifier: 1.5.4
- version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(71a760b327c31dd12606432855d01199))
+ version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(4c76b7da14d170b1922a58fb44839507))
'@better-auth/sso':
specifier: 1.5.4
- version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(71a760b327c31dd12606432855d01199))(better-call@2.0.2(zod@4.3.6))
+ version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(4c76b7da14d170b1922a58fb44839507))(better-call@2.0.2(zod@4.3.6))
'@codemirror/autocomplete':
specifier: ^6.18.6
version: 6.20.0
@@ -244,7 +244,7 @@ importers:
version: 11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3)
'@trpc/next':
specifier: ^11.10.0
- version: 11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(react@18.2.0)(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)
+ version: 11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(react@18.2.0)(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)
'@trpc/react-query':
specifier: ^11.10.0
version: 11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(react@18.2.0)(typescript@5.9.3)
@@ -280,7 +280,7 @@ importers:
version: 5.1.1(encoding@0.1.13)
better-auth:
specifier: 1.5.4
- version: 1.5.4(71a760b327c31dd12606432855d01199)
+ version: 1.5.4(4c76b7da14d170b1922a58fb44839507)
bl:
specifier: 6.0.11
version: 6.0.11
@@ -342,14 +342,14 @@ importers:
specifier: 3.3.11
version: 3.3.11
next:
- specifier: ^16.2.0
- version: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ specifier: 16.2.6
+ version: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
next-themes:
specifier: ^0.2.1
- version: 0.2.1(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ version: 0.2.1(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
nextjs-toploader:
specifier: ^3.9.17
- version: 3.9.17(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ version: 3.9.17(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
node-os-utils:
specifier: 2.0.1
version: 2.0.1
@@ -630,10 +630,10 @@ importers:
version: 2.0.30(zod@4.3.6)
'@better-auth/api-key':
specifier: 1.5.4
- version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9))
+ version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(9312701f7238452a4ac943b2bb39c424))
'@better-auth/sso':
specifier: 1.5.4
- version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9))(better-call@2.0.2(zod@4.3.6))
+ version: 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(9312701f7238452a4ac943b2bb39c424))(better-call@2.0.2(zod@4.3.6))
'@better-auth/utils':
specifier: 0.3.1
version: 0.3.1
@@ -672,7 +672,7 @@ importers:
version: 5.1.1(encoding@0.1.13)
better-auth:
specifier: 1.5.4
- version: 1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9)
+ version: 1.5.4(9312701f7238452a4ac943b2bb39c424)
better-call:
specifier: 2.0.2
version: 2.0.2(zod@4.3.6)
@@ -775,7 +775,7 @@ importers:
devDependencies:
'@better-auth/cli':
specifier: 1.4.21
- version: 1.4.21(@better-fetch/fetch@1.1.21)(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(better-call@2.0.2(zod@4.3.6))(drizzle-kit@0.31.9)(jose@6.1.3)(kysely@0.28.11)(mongodb@7.1.0(socks@2.8.8))(mysql2@3.15.3)(nanostores@1.1.1)(next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1))
+ version: 1.4.21(@better-fetch/fetch@1.1.21)(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(better-call@2.0.2(zod@4.3.6))(drizzle-kit@0.31.9)(jose@6.1.3)(kysely@0.28.11)(mongodb@7.1.0(socks@2.8.8))(mysql2@3.15.3)(nanostores@1.1.1)(next@16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1))
'@types/adm-zip':
specifier: ^0.5.7
version: 0.5.7
@@ -1878,53 +1878,53 @@ packages:
cpu: [x64]
os: [win32]
- '@next/env@16.2.0':
- resolution: {integrity: sha512-OZIbODWWAi0epQRCRjNe1VO45LOFBzgiyqmTLzIqWq6u1wrxKnAyz1HH6tgY/Mc81YzIjRPoYsPAEr4QV4l9TA==}
+ '@next/env@16.2.6':
+ resolution: {integrity: sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==}
- '@next/swc-darwin-arm64@16.2.0':
- resolution: {integrity: sha512-/JZsqKzKt01IFoiLLAzlNqys7qk2F3JkcUhj50zuRhKDQkZNOz9E5N6wAQWprXdsvjRP4lTFj+/+36NSv5AwhQ==}
+ '@next/swc-darwin-arm64@16.2.6':
+ resolution: {integrity: sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@16.2.0':
- resolution: {integrity: sha512-/hV8erWq4SNlVgglUiW5UmQ5Hwy5EW/AbbXlJCn6zkfKxTy/E/U3V8U1Ocm2YCTUoFgQdoMxRyRMOW5jYy4ygg==}
+ '@next/swc-darwin-x64@16.2.6':
+ resolution: {integrity: sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@16.2.0':
- resolution: {integrity: sha512-GkjL/Q7MWOwqWR9zoxu1TIHzkOI2l2BHCf7FzeQG87zPgs+6WDh+oC9Sw9ARuuL/FUk6JNCgKRkA6rEQYadUaw==}
+ '@next/swc-linux-arm64-gnu@16.2.6':
+ resolution: {integrity: sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@16.2.0':
- resolution: {integrity: sha512-1ffhC6KY5qWLg5miMlKJp3dZbXelEfjuXt1qcp5WzSCQy36CV3y+JT7OC1WSFKizGQCDOcQbfkH/IjZP3cdRNA==}
+ '@next/swc-linux-arm64-musl@16.2.6':
+ resolution: {integrity: sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@16.2.0':
- resolution: {integrity: sha512-FmbDcZQ8yJRq93EJSL6xaE0KK/Rslraf8fj1uViGxg7K4CKBCRYSubILJPEhjSgZurpcPQq12QNOJQ0DRJl6Hg==}
+ '@next/swc-linux-x64-gnu@16.2.6':
+ resolution: {integrity: sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@16.2.0':
- resolution: {integrity: sha512-HzjIHVkmGAwRbh/vzvoBWWEbb8BBZPxBvVbDQDvzHSf3D8RP/4vjw7MNLDXFF9Q1WEzeQyEj2zdxBtVAHu5Oyw==}
+ '@next/swc-linux-x64-musl@16.2.6':
+ resolution: {integrity: sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@16.2.0':
- resolution: {integrity: sha512-UMiFNQf5H7+1ZsZPxEsA064WEuFbRNq/kEXyepbCnSErp4f5iut75dBA8UeerFIG3vDaQNOfCpevnERPp2V+nA==}
+ '@next/swc-win32-arm64-msvc@16.2.6':
+ resolution: {integrity: sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@16.2.0':
- resolution: {integrity: sha512-DRrNJKW+/eimrZgdhVN1uvkN1OI4j6Lpefwr44jKQ0YQzztlmOBUUzHuV5GxOMPK3nmodAYElUVCY8ZXo/IWeA==}
+ '@next/swc-win32-x64-msvc@16.2.6':
+ resolution: {integrity: sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -4171,6 +4171,7 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+ deprecated: Potential CWE-502 - Update to 1.3.1 or higher
'@vercel/oidc@3.1.0':
resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
@@ -6565,8 +6566,8 @@ packages:
react: '*'
react-dom: '*'
- next@16.2.0:
- resolution: {integrity: sha512-NLBVrJy1pbV1Yn00L5sU4vFyAHt5XuSjzrNyFnxo6Com0M0KrL6hHM5B99dbqXb2bE9pm4Ow3Zl1xp6HVY9edQ==}
+ next@16.2.6:
+ resolution: {integrity: sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==}
engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
@@ -8664,21 +8665,21 @@ snapshots:
'@balena/dockerignore@1.0.2': {}
- '@better-auth/api-key@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9))':
+ '@better-auth/api-key@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(4c76b7da14d170b1922a58fb44839507))':
dependencies:
'@better-auth/core': 1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1)
'@better-auth/utils': 0.3.1
- better-auth: 1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9)
+ better-auth: 1.5.4(4c76b7da14d170b1922a58fb44839507)
zod: 4.3.6
- '@better-auth/api-key@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(71a760b327c31dd12606432855d01199))':
+ '@better-auth/api-key@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(9312701f7238452a4ac943b2bb39c424))':
dependencies:
'@better-auth/core': 1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1)
'@better-auth/utils': 0.3.1
- better-auth: 1.5.4(71a760b327c31dd12606432855d01199)
+ better-auth: 1.5.4(9312701f7238452a4ac943b2bb39c424)
zod: 4.3.6
- '@better-auth/cli@1.4.21(@better-fetch/fetch@1.1.21)(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(better-call@2.0.2(zod@4.3.6))(drizzle-kit@0.31.9)(jose@6.1.3)(kysely@0.28.11)(mongodb@7.1.0(socks@2.8.8))(mysql2@3.15.3)(nanostores@1.1.1)(next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1))':
+ '@better-auth/cli@1.4.21(@better-fetch/fetch@1.1.21)(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(better-call@2.0.2(zod@4.3.6))(drizzle-kit@0.31.9)(jose@6.1.3)(kysely@0.28.11)(mongodb@7.1.0(socks@2.8.8))(mysql2@3.15.3)(nanostores@1.1.1)(next@16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.29.0
'@babel/preset-react': 7.28.5(@babel/core@7.29.0)
@@ -8690,7 +8691,7 @@ snapshots:
'@mrleebo/prisma-ast': 0.13.1
'@prisma/client': 5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))
'@types/pg': 8.16.0
- better-auth: 1.4.21(97e31320bc7dc8a33b04861de973b388)
+ better-auth: 1.4.21(23a7835d44d42e8df1218333453e2b24)
better-sqlite3: 12.6.2
c12: 3.3.3
chalk: 5.6.2
@@ -8824,24 +8825,24 @@ snapshots:
'@prisma/client': 5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))
prisma: 7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)
- '@better-auth/sso@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9))(better-call@2.0.2(zod@4.3.6))':
+ '@better-auth/sso@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(4c76b7da14d170b1922a58fb44839507))(better-call@2.0.2(zod@4.3.6))':
dependencies:
'@better-auth/core': 1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1)
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
- better-auth: 1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9)
+ better-auth: 1.5.4(4c76b7da14d170b1922a58fb44839507)
better-call: 2.0.2(zod@4.3.6)
fast-xml-parser: 5.5.1
jose: 6.1.3
samlify: 2.10.2
zod: 4.3.6
- '@better-auth/sso@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(71a760b327c31dd12606432855d01199))(better-call@2.0.2(zod@4.3.6))':
+ '@better-auth/sso@1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(better-auth@1.5.4(9312701f7238452a4ac943b2bb39c424))(better-call@2.0.2(zod@4.3.6))':
dependencies:
'@better-auth/core': 1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1)
'@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21
- better-auth: 1.5.4(71a760b327c31dd12606432855d01199)
+ better-auth: 1.5.4(9312701f7238452a4ac943b2bb39c424)
better-call: 2.0.2(zod@4.3.6)
fast-xml-parser: 5.5.1
jose: 6.1.3
@@ -9512,30 +9513,30 @@ snapshots:
'@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3':
optional: true
- '@next/env@16.2.0': {}
+ '@next/env@16.2.6': {}
- '@next/swc-darwin-arm64@16.2.0':
+ '@next/swc-darwin-arm64@16.2.6':
optional: true
- '@next/swc-darwin-x64@16.2.0':
+ '@next/swc-darwin-x64@16.2.6':
optional: true
- '@next/swc-linux-arm64-gnu@16.2.0':
+ '@next/swc-linux-arm64-gnu@16.2.6':
optional: true
- '@next/swc-linux-arm64-musl@16.2.0':
+ '@next/swc-linux-arm64-musl@16.2.6':
optional: true
- '@next/swc-linux-x64-gnu@16.2.0':
+ '@next/swc-linux-x64-gnu@16.2.6':
optional: true
- '@next/swc-linux-x64-musl@16.2.0':
+ '@next/swc-linux-x64-musl@16.2.6':
optional: true
- '@next/swc-win32-arm64-msvc@16.2.0':
+ '@next/swc-win32-arm64-msvc@16.2.6':
optional: true
- '@next/swc-win32-x64-msvc@16.2.0':
+ '@next/swc-win32-x64-msvc@16.2.6':
optional: true
'@noble/ciphers@2.1.1': {}
@@ -12026,11 +12027,11 @@ snapshots:
'@trpc/server': 11.10.0(typescript@5.9.3)
typescript: 5.9.3
- '@trpc/next@11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(react@18.2.0)(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)':
+ '@trpc/next@11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.10.0(@tanstack/react-query@5.90.21(react@18.2.0))(@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(react@18.2.0)(typescript@5.9.3))(@trpc/server@11.10.0(typescript@5.9.3))(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)':
dependencies:
'@trpc/client': 11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3)
'@trpc/server': 11.10.0(typescript@5.9.3)
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
typescript: 5.9.3
@@ -12534,7 +12535,7 @@ snapshots:
before-after-hook@2.2.3: {}
- better-auth@1.4.21(97e31320bc7dc8a33b04861de973b388):
+ better-auth@1.4.21(23a7835d44d42e8df1218333453e2b24):
dependencies:
'@better-auth/core': 1.4.21(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0)
'@better-auth/telemetry': 1.4.21(@better-auth/core@1.4.21(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))
@@ -12555,14 +12556,14 @@ snapshots:
drizzle-orm: 0.41.0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.11)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))
mongodb: 7.1.0(socks@2.8.8)
mysql2: 3.15.3
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
pg: 8.18.0
prisma: 7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1)
- better-auth@1.5.4(48b68ecaf84f5e14652b8d87fbbd7ca9):
+ better-auth@1.5.4(4c76b7da14d170b1922a58fb44839507):
dependencies:
'@better-auth/core': 1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1)
'@better-auth/drizzle-adapter': 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(drizzle-orm@0.45.1(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.11)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))
@@ -12588,16 +12589,16 @@ snapshots:
drizzle-orm: 0.45.1(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.11)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))
mongodb: 7.1.0(socks@2.8.8)
mysql2: 3.15.3
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
pg: 8.18.0
prisma: 7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1)
+ vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@1.21.7)(tsx@4.16.2)(yaml@2.8.1)
transitivePeerDependencies:
- '@cloudflare/workers-types'
- better-auth@1.5.4(71a760b327c31dd12606432855d01199):
+ better-auth@1.5.4(9312701f7238452a4ac943b2bb39c424):
dependencies:
'@better-auth/core': 1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1)
'@better-auth/drizzle-adapter': 1.5.4(@better-auth/core@1.5.4(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@2.0.2(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.1))(@better-auth/utils@0.3.1)(drizzle-orm@0.45.1(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.11)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))
@@ -12623,12 +12624,12 @@ snapshots:
drizzle-orm: 0.45.1(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.11)(mysql2@3.15.3)(pg@8.18.0)(postgres@3.4.4)(prisma@7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3))
mongodb: 7.1.0(socks@2.8.8)
mysql2: 3.15.3
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
pg: 8.18.0
prisma: 7.4.1(@types/react@18.3.5)(better-sqlite3@12.6.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.3)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@1.21.7)(tsx@4.16.2)(yaml@2.8.1)
+ vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.13)(jiti@2.6.1)(tsx@4.16.2)(yaml@2.8.1)
transitivePeerDependencies:
- '@cloudflare/workers-types'
@@ -13881,7 +13882,7 @@ snapshots:
inline-style-parser@0.2.7: {}
- inngest@3.40.1(encoding@0.1.13)(h3@1.15.1)(hono@4.12.2)(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(typescript@5.9.3):
+ inngest@3.40.1(encoding@0.1.13)(h3@1.15.1)(hono@4.12.2)(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(typescript@5.9.3):
dependencies:
'@bufbuild/protobuf': 2.11.0
'@inngest/ai': 0.1.7
@@ -13908,7 +13909,7 @@ snapshots:
optionalDependencies:
h3: 1.15.1
hono: 4.12.2
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
typescript: 5.9.3
transitivePeerDependencies:
- encoding
@@ -14704,15 +14705,15 @@ snapshots:
neotraverse@0.6.18: {}
- next-themes@0.2.1(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
+ next-themes@0.2.1(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
dependencies:
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
+ next@16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
dependencies:
- '@next/env': 16.2.0
+ '@next/env': 16.2.6
'@swc/helpers': 0.5.15
baseline-browser-mapping: 2.10.0
caniuse-lite: 1.0.30001774
@@ -14721,23 +14722,23 @@ snapshots:
react-dom: 18.2.0(react@18.2.0)
styled-jsx: 5.1.6(@babel/core@7.29.0)(react@18.2.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 16.2.0
- '@next/swc-darwin-x64': 16.2.0
- '@next/swc-linux-arm64-gnu': 16.2.0
- '@next/swc-linux-arm64-musl': 16.2.0
- '@next/swc-linux-x64-gnu': 16.2.0
- '@next/swc-linux-x64-musl': 16.2.0
- '@next/swc-win32-arm64-msvc': 16.2.0
- '@next/swc-win32-x64-msvc': 16.2.0
+ '@next/swc-darwin-arm64': 16.2.6
+ '@next/swc-darwin-x64': 16.2.6
+ '@next/swc-linux-arm64-gnu': 16.2.6
+ '@next/swc-linux-arm64-musl': 16.2.6
+ '@next/swc-linux-x64-gnu': 16.2.6
+ '@next/swc-linux-x64-musl': 16.2.6
+ '@next/swc-win32-arm64-msvc': 16.2.6
+ '@next/swc-win32-x64-msvc': 16.2.6
'@opentelemetry/api': 1.9.0
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
- nextjs-toploader@3.9.17(next@16.2.0(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
+ nextjs-toploader@3.9.17(next@16.2.6(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
dependencies:
- next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ next: 16.2.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
nprogress: 0.2.0
prop-types: 15.8.1
react: 18.2.0