Merge branch 'canary' into Volume-Backup-Notification-#2875

This commit is contained in:
Mauricio Siu
2025-12-07 02:04:00 -06:00
212 changed files with 96978 additions and 5077 deletions

View File

@@ -9,7 +9,7 @@ import {
import { nanoid } from "nanoid";
import { projects } from "./project";
import { server } from "./server";
import { users_temp } from "./user";
import { user } from "./user";
export const account = pgTable("account", {
id: text("id")
@@ -21,7 +21,7 @@ export const account = pgTable("account", {
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
@@ -39,9 +39,9 @@ export const account = pgTable("account", {
});
export const accountRelations = relations(account, ({ one }) => ({
user: one(users_temp, {
user: one(user, {
fields: [account.userId],
references: [users_temp.id],
references: [user.id],
}),
}));
@@ -65,15 +65,15 @@ export const organization = pgTable("organization", {
metadata: text("metadata"),
ownerId: text("owner_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
});
export const organizationRelations = relations(
organization,
({ one, many }) => ({
owner: one(users_temp, {
owner: one(user, {
fields: [organization.ownerId],
references: [users_temp.id],
references: [user.id],
}),
servers: many(server),
projects: many(projects),
@@ -90,10 +90,11 @@ export const member = pgTable("member", {
.references(() => organization.id, { onDelete: "cascade" }),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
role: text("role").notNull().$type<"owner" | "member" | "admin">(),
createdAt: timestamp("created_at").notNull(),
teamId: text("team_id"),
isDefault: boolean("is_default").notNull().default(false),
// Permissions
canCreateProjects: boolean("canCreateProjects").notNull().default(false),
canAccessToSSHKeys: boolean("canAccessToSSHKeys").notNull().default(false),
@@ -133,9 +134,9 @@ export const memberRelations = relations(member, ({ one }) => ({
fields: [member.organizationId],
references: [organization.id],
}),
user: one(users_temp, {
user: one(user, {
fields: [member.userId],
references: [users_temp.id],
references: [user.id],
}),
}));
@@ -150,7 +151,7 @@ export const invitation = pgTable("invitation", {
expiresAt: timestamp("expires_at").notNull(),
inviterId: text("inviter_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
teamId: text("team_id"),
});
@@ -167,7 +168,7 @@ export const twoFactor = pgTable("two_factor", {
backupCodes: text("backup_codes").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
});
export const apikey = pgTable("apikey", {
@@ -178,7 +179,7 @@ export const apikey = pgTable("apikey", {
key: text("key").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
refillInterval: integer("refill_interval"),
refillAmount: integer("refill_amount"),
lastRefillAt: timestamp("last_refill_at"),
@@ -197,8 +198,8 @@ export const apikey = pgTable("apikey", {
});
export const apikeyRelations = relations(apikey, ({ one }) => ({
user: one(users_temp, {
user: one(user, {
fields: [apikey.userId],
references: [users_temp.id],
references: [user.id],
}),
}));

View File

@@ -28,6 +28,8 @@ import { server } from "./server";
import {
applicationStatus,
certificateType,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -80,6 +82,7 @@ export const applications = pgTable("application", {
previewEnv: text("previewEnv"),
watchPaths: text("watchPaths").array(),
previewBuildArgs: text("previewBuildArgs"),
previewBuildSecrets: text("previewBuildSecrets"),
previewLabels: text("previewLabels").array(),
previewWildcard: text("previewWildcard"),
previewPort: integer("previewPort").default(3000),
@@ -99,6 +102,7 @@ export const applications = pgTable("application", {
).default(true),
rollbackActive: boolean("rollbackActive").default(false),
buildArgs: text("buildArgs"),
buildSecrets: text("buildSecrets"),
memoryReservation: text("memoryReservation"),
memoryLimit: text("memoryLimit"),
cpuReservation: text("cpuReservation"),
@@ -107,6 +111,7 @@ export const applications = pgTable("application", {
enabled: boolean("enabled"),
subtitle: text("subtitle"),
command: text("command"),
args: text("args").array(),
refreshToken: text("refreshToken").$defaultFn(() => nanoid()),
sourceType: sourceType("sourceType").notNull().default("github"),
cleanCache: boolean("cleanCache").default(false),
@@ -165,6 +170,7 @@ export const applications = pgTable("application", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
//
replicas: integer("replicas").default(1).notNull(),
applicationStatus: applicationStatus("applicationStatus")
@@ -181,6 +187,12 @@ export const applications = pgTable("application", {
registryId: text("registryId").references(() => registry.registryId, {
onDelete: "set null",
}),
rollbackRegistryId: text("rollbackRegistryId").references(
() => registry.registryId,
{
onDelete: "set null",
},
),
environmentId: text("environmentId")
.notNull()
.references(() => environments.environmentId, { onDelete: "cascade" }),
@@ -199,6 +211,15 @@ export const applications = pgTable("application", {
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
buildServerId: text("buildServerId").references(() => server.serverId, {
onDelete: "set null",
}),
buildRegistryId: text("buildRegistryId").references(
() => registry.registryId,
{
onDelete: "set null",
},
),
});
export const applicationsRelations = relations(
@@ -221,6 +242,7 @@ export const applicationsRelations = relations(
registry: one(registry, {
fields: [applications.registryId],
references: [registry.registryId],
relationName: "applicationRegistry",
}),
github: one(github, {
fields: [applications.githubId],
@@ -241,8 +263,24 @@ export const applicationsRelations = relations(
server: one(server, {
fields: [applications.serverId],
references: [server.serverId],
relationName: "applicationServer",
}),
buildServer: one(server, {
fields: [applications.buildServerId],
references: [server.serverId],
relationName: "applicationBuildServer",
}),
buildRegistry: one(registry, {
fields: [applications.buildRegistryId],
references: [registry.registryId],
relationName: "applicationBuildRegistry",
}),
previewDeployments: many(previewDeployments),
rollbackRegistry: one(registry, {
fields: [applications.rollbackRegistryId],
references: [registry.registryId],
relationName: "applicationRollbackRegistry",
}),
}),
);
@@ -253,6 +291,7 @@ const createSchema = createInsertSchema(applications, {
autoDeploy: z.boolean(),
env: z.string().optional(),
buildArgs: z.string().optional(),
buildSecrets: z.string().optional(),
name: z.string().min(1),
description: z.string().optional(),
memoryReservation: z.string().optional(),
@@ -266,6 +305,7 @@ const createSchema = createInsertSchema(applications, {
username: z.string().optional(),
isPreviewDeploymentsActive: z.boolean().optional(),
password: z.string().optional(),
args: z.array(z.string()).optional(),
registryUrl: z.string().optional(),
customGitSSHKeyId: z.string().optional(),
repository: z.string().optional(),
@@ -304,6 +344,7 @@ const createSchema = createInsertSchema(applications, {
previewPort: z.number().optional(),
previewEnv: z.string().optional(),
previewBuildArgs: z.string().optional(),
previewBuildSecrets: z.string().optional(),
previewWildcard: z.string().optional(),
previewLimit: z.number().optional(),
previewHttps: z.boolean().optional(),
@@ -314,6 +355,7 @@ const createSchema = createInsertSchema(applications, {
previewLabels: z.array(z.string()).optional(),
cleanCache: z.boolean().optional(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateApplication = createSchema.pick({
@@ -458,6 +500,7 @@ export const apiSaveEnvironmentVariables = createSchema
applicationId: true,
env: true,
buildArgs: true,
buildSecrets: true,
})
.required();

View File

@@ -19,7 +19,7 @@ import { mariadb } from "./mariadb";
import { mongo } from "./mongo";
import { mysql } from "./mysql";
import { postgres } from "./postgres";
import { users_temp } from "./user";
import { user } from "./user";
export const databaseType = pgEnum("databaseType", [
"postgres",
"mariadb",
@@ -74,7 +74,7 @@ export const backups = pgTable("backup", {
mongoId: text("mongoId").references((): AnyPgColumn => mongo.mongoId, {
onDelete: "cascade",
}),
userId: text("userId").references(() => users_temp.id),
userId: text("userId").references(() => user.id),
// Only for compose backups
metadata: jsonb("metadata").$type<
| {
@@ -118,9 +118,9 @@ export const backupsRelations = relations(backups, ({ one, many }) => ({
fields: [backups.mongoId],
references: [mongo.mongoId],
}),
user: one(users_temp, {
user: one(user, {
fields: [backups.userId],
references: [users_temp.id],
references: [user.id],
}),
compose: one(compose, {
fields: [backups.composeId],

View File

@@ -12,7 +12,6 @@ import { gitea } from "./gitea";
import { github } from "./github";
import { gitlab } from "./gitlab";
import { mounts } from "./mount";
import { projects } from "./project";
import { schedules } from "./schedule";
import { server } from "./server";
import { applicationStatus, triggerType } from "./shared";

View File

@@ -70,6 +70,9 @@ export const deployments = pgTable("deployment", {
(): AnyPgColumn => volumeBackups.volumeBackupId,
{ onDelete: "cascade" },
),
buildServerId: text("buildServerId").references(() => server.serverId, {
onDelete: "cascade",
}),
});
export const deploymentsRelations = relations(deployments, ({ one }) => ({
@@ -84,6 +87,12 @@ export const deploymentsRelations = relations(deployments, ({ one }) => ({
server: one(server, {
fields: [deployments.serverId],
references: [server.serverId],
relationName: "deploymentServer",
}),
buildServer: one(server, {
fields: [deployments.buildServerId],
references: [server.serverId],
relationName: "deploymentBuildServer",
}),
previewDeployment: one(previewDeployments, {
fields: [deployments.previewDeploymentId],
@@ -115,6 +124,7 @@ const schema = createInsertSchema(deployments, {
composeId: z.string(),
description: z.string().optional(),
previewDeploymentId: z.string(),
buildServerId: z.string(),
});
export const apiCreateDeployment = schema

View File

@@ -8,7 +8,7 @@ import { bitbucket } from "./bitbucket";
import { gitea } from "./gitea";
import { github } from "./github";
import { gitlab } from "./gitlab";
import { users_temp } from "./user";
import { user } from "./user";
export const gitProviderType = pgEnum("gitProviderType", [
"github",
@@ -32,7 +32,7 @@ export const gitProvider = pgTable("git_provider", {
.references(() => organization.id, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
});
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
@@ -56,9 +56,9 @@ export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
fields: [gitProvider.organizationId],
references: [organization.id],
}),
user: one(users_temp, {
user: one(user, {
fields: [gitProvider.userId],
references: [users_temp.id],
references: [user.id],
}),
}));

View File

@@ -9,6 +9,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -43,6 +45,7 @@ export const mariadb = pgTable("mariadb", {
databaseRootPassword: text("rootPassword").notNull(),
dockerImage: text("dockerImage").notNull(),
command: text("command"),
args: text("args").array(),
env: text("env"),
// RESOURCES
memoryReservation: text("memoryReservation"),
@@ -63,6 +66,7 @@ export const mariadb = pgTable("mariadb", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -111,6 +115,7 @@ const createSchema = createInsertSchema(mariadb, {
.optional(),
dockerImage: z.string().default("mariadb:6"),
command: z.string().optional(),
args: z.array(z.string()).optional(),
env: z.string().optional(),
memoryReservation: z.string().optional(),
memoryLimit: z.string().optional(),
@@ -130,6 +135,7 @@ const createSchema = createInsertSchema(mariadb, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateMariaDB = createSchema

View File

@@ -16,6 +16,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -48,6 +50,7 @@ export const mongo = pgTable("mongo", {
databasePassword: text("databasePassword").notNull(),
dockerImage: text("dockerImage").notNull(),
command: text("command"),
args: text("args").array(),
env: text("env"),
memoryReservation: text("memoryReservation"),
memoryLimit: text("memoryLimit"),
@@ -66,6 +69,7 @@ export const mongo = pgTable("mongo", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -107,6 +111,7 @@ const createSchema = createInsertSchema(mongo, {
databaseUser: z.string().min(1),
dockerImage: z.string().default("mongo:15"),
command: z.string().optional(),
args: z.array(z.string()).optional(),
env: z.string().optional(),
memoryReservation: z.string().optional(),
memoryLimit: z.string().optional(),
@@ -127,6 +132,7 @@ const createSchema = createInsertSchema(mongo, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateMongo = createSchema

View File

@@ -9,6 +9,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -43,6 +45,7 @@ export const mysql = pgTable("mysql", {
databaseRootPassword: text("rootPassword").notNull(),
dockerImage: text("dockerImage").notNull(),
command: text("command"),
args: text("args").array(),
env: text("env"),
memoryReservation: text("memoryReservation"),
memoryLimit: text("memoryLimit"),
@@ -61,6 +64,7 @@ export const mysql = pgTable("mysql", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -109,6 +113,7 @@ const createSchema = createInsertSchema(mysql, {
.optional(),
dockerImage: z.string().default("mysql:8"),
command: z.string().optional(),
args: z.array(z.string()).optional(),
env: z.string().optional(),
memoryReservation: z.string().optional(),
memoryLimit: z.string().optional(),
@@ -127,6 +132,7 @@ const createSchema = createInsertSchema(mysql, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateMySql = createSchema

View File

@@ -12,6 +12,7 @@ export const notificationType = pgEnum("notificationType", [
"email",
"gotify",
"ntfy",
"lark",
]);
export const notifications = pgTable("notification", {
@@ -49,6 +50,9 @@ export const notifications = pgTable("notification", {
ntfyId: text("ntfyId").references(() => ntfy.ntfyId, {
onDelete: "cascade",
}),
larkId: text("larkId").references(() => lark.larkId, {
onDelete: "cascade",
}),
organizationId: text("organizationId")
.notNull()
.references(() => organization.id, { onDelete: "cascade" }),
@@ -113,10 +117,18 @@ export const ntfy = pgTable("ntfy", {
.$defaultFn(() => nanoid()),
serverUrl: text("serverUrl").notNull(),
topic: text("topic").notNull(),
accessToken: text("accessToken").notNull(),
accessToken: text("accessToken"),
priority: integer("priority").notNull().default(3),
});
export const lark = pgTable("lark", {
larkId: text("larkId")
.notNull()
.primaryKey()
.$defaultFn(() => nanoid()),
webhookUrl: text("webhookUrl").notNull(),
});
export const notificationsRelations = relations(notifications, ({ one }) => ({
slack: one(slack, {
fields: [notifications.slackId],
@@ -142,6 +154,10 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({
fields: [notifications.ntfyId],
references: [ntfy.ntfyId],
}),
lark: one(lark, {
fields: [notifications.larkId],
references: [lark.larkId],
}),
organization: one(organization, {
fields: [notifications.organizationId],
references: [organization.id],
@@ -322,7 +338,7 @@ export const apiCreateNtfy = notificationsSchema
.extend({
serverUrl: z.string().min(1),
topic: z.string().min(1),
accessToken: z.string().min(1),
accessToken: z.string().optional(),
priority: z.number().min(1),
})
.required();
@@ -346,6 +362,31 @@ export const apiFindOneNotification = notificationsSchema
})
.required();
export const apiCreateLark = notificationsSchema
.pick({
appBuildError: true,
databaseBackup: true,
dokployRestart: true,
name: true,
appDeploy: true,
dockerCleanup: true,
serverThreshold: true,
})
.extend({
webhookUrl: z.string().min(1),
})
.required();
export const apiUpdateLark = apiCreateLark.partial().extend({
notificationId: z.string().min(1),
larkId: z.string().min(1),
organizationId: z.string().optional(),
});
export const apiTestLarkConnection = apiCreateLark.pick({
webhookUrl: true,
});
export const apiSendTest = notificationsSchema
.extend({
botToken: z.string(),
@@ -361,7 +402,7 @@ export const apiSendTest = notificationsSchema
serverUrl: z.string(),
topic: z.string(),
appToken: z.string(),
accessToken: z.string(),
accessToken: z.string().optional(),
priority: z.number(),
})
.partial();

View File

@@ -9,6 +9,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -42,6 +44,7 @@ export const postgres = pgTable("postgres", {
description: text("description"),
dockerImage: text("dockerImage").notNull(),
command: text("command"),
args: text("args").array(),
env: text("env"),
memoryReservation: text("memoryReservation"),
externalPort: integer("externalPort"),
@@ -61,6 +64,7 @@ export const postgres = pgTable("postgres", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -100,6 +104,7 @@ const createSchema = createInsertSchema(postgres, {
databaseUser: z.string().min(1),
dockerImage: z.string().default("postgres:15"),
command: z.string().optional(),
args: z.array(z.string()).optional(),
env: z.string().optional(),
memoryReservation: z.string().optional(),
memoryLimit: z.string().optional(),
@@ -120,6 +125,7 @@ const createSchema = createInsertSchema(postgres, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreatePostgres = createSchema

View File

@@ -5,10 +5,11 @@ import { nanoid } from "nanoid";
import { z } from "zod";
import { environments } from "./environment";
import { mounts } from "./mount";
import { projects } from "./project";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -40,6 +41,7 @@ export const redis = pgTable("redis", {
databasePassword: text("password").notNull(),
dockerImage: text("dockerImage").notNull(),
command: text("command"),
args: text("args").array(),
env: text("env"),
memoryReservation: text("memoryReservation"),
memoryLimit: text("memoryLimit"),
@@ -61,6 +63,7 @@ export const redis = pgTable("redis", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
environmentId: text("environmentId")
@@ -91,6 +94,7 @@ const createSchema = createInsertSchema(redis, {
databasePassword: z.string(),
dockerImage: z.string().default("redis:8"),
command: z.string().optional(),
args: z.array(z.string()).optional(),
env: z.string().optional(),
memoryReservation: z.string().optional(),
memoryLimit: z.string().optional(),
@@ -110,6 +114,7 @@ const createSchema = createInsertSchema(redis, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateRedis = createSchema

View File

@@ -33,7 +33,15 @@ export const registry = pgTable("registry", {
});
export const registryRelations = relations(registry, ({ many }) => ({
applications: many(applications),
applications: many(applications, {
relationName: "applicationRegistry",
}),
buildApplications: many(applications, {
relationName: "applicationBuildRegistry",
}),
rollbackApplications: many(applications, {
relationName: "applicationRollbackRegistry",
}),
}));
const createSchema = createInsertSchema(registry, {

View File

@@ -7,7 +7,7 @@ import { applications } from "./application";
import { compose } from "./compose";
import { deployments } from "./deployment";
import { server } from "./server";
import { users_temp } from "./user";
import { user } from "./user";
import { generateAppName } from "./utils";
export const shellTypes = pgEnum("shellType", ["bash", "sh"]);
@@ -45,7 +45,7 @@ export const schedules = pgTable("schedule", {
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
userId: text("userId").references(() => users_temp.id, {
userId: text("userId").references(() => user.id, {
onDelete: "cascade",
}),
enabled: boolean("enabled").notNull().default(true),
@@ -69,9 +69,9 @@ export const schedulesRelations = relations(schedules, ({ one, many }) => ({
fields: [schedules.serverId],
references: [server.serverId],
}),
user: one(users_temp, {
user: one(user, {
fields: [schedules.userId],
references: [users_temp.id],
references: [user.id],
}),
deployments: many(deployments),
}));

View File

@@ -24,6 +24,7 @@ import { schedules } from "./schedule";
import { sshKeys } from "./ssh-key";
import { generateAppName } from "./utils";
export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]);
export const serverType = pgEnum("serverType", ["deploy", "build"]);
export const server = pgTable("server", {
serverId: text("serverId")
@@ -44,6 +45,7 @@ export const server = pgTable("server", {
.notNull()
.references(() => organization.id, { onDelete: "cascade" }),
serverStatus: serverStatus("serverStatus").notNull().default("active"),
serverType: serverType("serverType").notNull().default("deploy"),
command: text("command").notNull().default(""),
sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, {
onDelete: "set null",
@@ -97,12 +99,22 @@ export const server = pgTable("server", {
});
export const serverRelations = relations(server, ({ one, many }) => ({
deployments: many(deployments),
deployments: many(deployments, {
relationName: "deploymentServer",
}),
buildDeployments: many(deployments, {
relationName: "deploymentBuildServer",
}),
sshKey: one(sshKeys, {
fields: [server.sshKeyId],
references: [sshKeys.sshKeyId],
}),
applications: many(applications),
applications: many(applications, {
relationName: "applicationServer",
}),
buildApplications: many(applications, {
relationName: "applicationBuildServer",
}),
compose: many(compose),
redis: many(redis),
mariadb: many(mariadb),
@@ -131,6 +143,7 @@ export const apiCreateServer = createSchema
port: true,
username: true,
sshKeyId: true,
serverType: true,
})
.required();
@@ -155,6 +168,7 @@ export const apiUpdateServer = createSchema
port: true,
username: true,
sshKeyId: true,
serverType: true,
})
.required()
.extend({

View File

@@ -1,5 +1,5 @@
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { users_temp } from "./user";
import { user } from "./user";
// OLD TABLE
export const session = pgTable("session_temp", {
@@ -12,7 +12,7 @@ export const session = pgTable("session_temp", {
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
impersonatedBy: text("impersonated_by"),
activeOrganizationId: text("active_organization_id"),
});

View File

@@ -74,6 +74,18 @@ export interface LabelsSwarm {
[name: string]: string;
}
export interface EndpointPortConfigSwarm {
Protocol?: string | undefined;
TargetPort?: number | undefined;
PublishedPort?: number | undefined;
PublishMode?: string | undefined;
}
export interface EndpointSpecSwarm {
Mode?: string | undefined;
Ports?: EndpointPortConfigSwarm[] | undefined;
}
export const HealthCheckSwarmSchema = z
.object({
Test: z.array(z.string()).optional(),
@@ -161,3 +173,19 @@ export const NetworkSwarmSchema = z.array(
);
export const LabelsSwarmSchema = z.record(z.string());
export const EndpointPortConfigSwarmSchema = z
.object({
Protocol: z.string().optional(),
TargetPort: z.number().optional(),
PublishedPort: z.number().optional(),
PublishMode: z.string().optional(),
})
.strict();
export const EndpointSpecSwarmSchema = z
.object({
Mode: z.string().optional(),
Ports: z.array(EndpointPortConfigSwarmSchema).optional(),
})
.strict();

View File

@@ -26,7 +26,7 @@ import { certificateType } from "./shared";
// OLD TABLE
// TEMP
export const users_temp = pgTable("user_temp", {
export const user = pgTable("user", {
id: text("id")
.notNull()
.primaryKey()
@@ -56,7 +56,7 @@ export const users_temp = pgTable("user_temp", {
host: text("host"),
letsEncryptEmail: text("letsEncryptEmail"),
sshPrivateKey: text("sshPrivateKey"),
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(true),
logCleanupCron: text("logCleanupCron").default("0 0 * * *"),
role: text("role").notNull().default("user"),
// Metrics
@@ -122,9 +122,9 @@ export const users_temp = pgTable("user_temp", {
serversQuantity: integer("serversQuantity").notNull().default(0),
});
export const usersRelations = relations(users_temp, ({ one, many }) => ({
export const usersRelations = relations(user, ({ one, many }) => ({
account: one(account, {
fields: [users_temp.id],
fields: [user.id],
references: [account.userId],
}),
organizations: many(organization),
@@ -134,7 +134,7 @@ export const usersRelations = relations(users_temp, ({ one, many }) => ({
schedules: many(schedules),
}));
const createSchema = createInsertSchema(users_temp, {
const createSchema = createInsertSchema(user, {
id: z.string().min(1),
isRegistered: z.boolean().optional(),
}).omit({

View File

@@ -2,7 +2,13 @@ import { z } from "zod";
export const domain = z
.object({
host: z.string().min(1, { message: "Add a hostname" }),
host: z
.string()
.min(1, { message: "Add a hostname" })
.refine((val) => val === val.trim(), {
message: "Domain name cannot have leading or trailing spaces",
})
.transform((val) => val.trim()),
path: z.string().min(1).optional(),
internalPath: z.string().optional(),
stripPath: z.boolean().optional(),
@@ -58,7 +64,13 @@ export const domain = z
export const domainCompose = z
.object({
host: z.string().min(1, { message: "Host is required" }),
host: z
.string()
.min(1, { message: "Add a hostname" })
.refine((val) => val === val.trim(), {
message: "Domain name cannot have leading or trailing spaces",
})
.transform((val) => val.trim()),
path: z.string().min(1).optional(),
internalPath: z.string().optional(),
stripPath: z.boolean().optional(),