Adding methods to delete backups on remote storage s3 and local. Some refactoring on models db and adding common.ts model with createdAt, updatedAt, and deletedAt.

This commit is contained in:
charlesgauthereau
2025-08-29 15:31:23 +02:00
parent c8da2579e8
commit 45e3b31fda
48 changed files with 310 additions and 148 deletions
+8 -8
View File
@@ -1,13 +1,13 @@
import {drizzle} from "drizzle-orm/node-postgres";
import * as settings from "./schema/00_setting";
import * as user from "./schema/01_user";
import * as organisation from "./schema/02_organization";
import * as invitation from "./schema/03_member";
import * as member from "./schema/04_invitation";
import * as project from "./schema/05_project";
import * as agent from "./schema/07_agent";
import * as database from "./schema/06_database";
import * as settings from "./schema/01_setting";
import * as user from "./schema/02_user";
import * as organisation from "./schema/03_organization";
import * as invitation from "./schema/04_member";
import * as member from "./schema/05_invitation";
import * as project from "./schema/06_project";
import * as agent from "./schema/08_agent";
import * as database from "./schema/07_database";
import {Pool} from "pg";
+7
View File
@@ -29,6 +29,13 @@
"when": 1756321312852,
"tag": "0003_absent_maestro",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1756473637441,
"tag": "0004_dazzling_hawkeye",
"breakpoints": true
}
]
}
+15
View File
@@ -0,0 +1,15 @@
import {timestamp} from "drizzle-orm/pg-core";
import {z} from "zod";
export const timestamps = {
updatedAt: timestamp("updated_at"),
createdAt: timestamp("created_at").defaultNow().notNull(),
deletedAt: timestamp("deleted_at"),
}
export function schemaWithoutMeta<
T extends z.ZodTypeAny
>(schema: T) {
// @ts-ignore
return schema.omit({id: true, createdAt: true, updatedAt: true, deletedAt: true});
}
@@ -2,6 +2,7 @@ import { pgTable, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
import { typeStorageEnum } from "./types";
import { createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import {timestamps} from "@/db/schema/00_common";
export const setting = pgTable("settings", {
id: uuid("id").primaryKey().defaultRandom(),
@@ -16,8 +17,7 @@ export const setting = pgTable("settings", {
smtpHost: varchar("smtp_host", { length: 255 }),
smtpPort: varchar("smtp_port", { length: 255 }),
smtpUser: varchar("smtp_user", { length: 255 }),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
...timestamps
});
export const settingSchema = createSelectSchema(setting);
@@ -1,12 +1,13 @@
import { relations } from "drizzle-orm";
import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import { project } from "./05_project";
import {member, OrganizationMember} from "@/db/schema/03_member";
import {invitation} from "@/db/schema/04_invitation";
import {organization} from "@/db/schema/02_organization";
import {relations} from "drizzle-orm";
import {boolean, pgTable, text, timestamp, uuid} from "drizzle-orm/pg-core";
import {createSelectSchema} from "drizzle-zod";
import {z} from "zod";
import {project} from "./06_project";
import {member, OrganizationMember} from "@/db/schema/04_member";
import {invitation} from "@/db/schema/05_invitation";
import {organization} from "@/db/schema/03_organization";
import {Account} from "better-auth";
import {timestamps} from "@/db/schema/00_common";
export const user = pgTable("user", {
id: uuid("id").defaultRandom().primaryKey(),
@@ -14,28 +15,26 @@ export const user = pgTable("user", {
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified").notNull(),
image: text("image"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
role: text("role"),
banned: boolean("banned"),
banReason: text("ban_reason"),
banExpires: timestamp("ban_expires"),
deletedAt: timestamp("deleted_at"),
...timestamps
});
export const session = pgTable("session", {
id: uuid("id").defaultRandom().primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: uuid("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
.references(() => user.id, {onDelete: "cascade"}),
impersonatedBy: text("impersonated_by"), //id or name ????
activeOrganizationId: text("active_organization_id"),
...timestamps
});
export const account = pgTable("account", {
@@ -44,7 +43,7 @@ export const account = pgTable("account", {
providerId: text("provider_id").notNull(),
userId: uuid("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
.references(() => user.id, {onDelete: "cascade"}),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
@@ -52,8 +51,8 @@ export const account = pgTable("account", {
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
...timestamps
});
export const verification = pgTable("verification", {
@@ -61,32 +60,32 @@ export const verification = pgTable("verification", {
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
...timestamps
});
export const userRelations = relations(user, ({ many }) => ({
export const userRelations = relations(user, ({many}) => ({
sessions: many(session),
accounts: many(account),
memberships: many(member),
invitations: many(invitation),
}));
export const sessionRelations = relations(session, ({ one }) => ({
export const sessionRelations = relations(session, ({one}) => ({
user: one(user, {
fields: [session.userId],
references: [user.id],
}),
}));
export const accountRelations = relations(account, ({ one }) => ({
export const accountRelations = relations(account, ({one}) => ({
user: one(user, {
fields: [account.userId],
references: [user.id],
}),
}));
export const projectRelations = relations(project, ({ one }) => ({
export const projectRelations = relations(project, ({one}) => ({
organization: one(organization, {
fields: [project.organizationId],
references: [organization.id],
@@ -1,20 +1,20 @@
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { project } from "./05_project";
import { project } from "./06_project";
import { createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import {invitation, OrganizationInvitation} from "@/db/schema/04_invitation";
import {member, OrganizationMember} from "@/db/schema/03_member";
import {User} from "@/db/schema/01_user";
import {invitation, OrganizationInvitation} from "@/db/schema/05_invitation";
import {member, OrganizationMember} from "@/db/schema/04_member";
import {User} from "@/db/schema/02_user";
import {timestamps} from "@/db/schema/00_common";
export const organization = pgTable("organization", {
id: uuid("id").defaultRandom().primaryKey(),
name: text("name").notNull(),
slug: text("slug").unique().notNull(),
logo: text("logo"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
metadata: text("metadata"),
...timestamps
});
@@ -1,9 +1,10 @@
import {pgTable, text, timestamp, uuid} from "drizzle-orm/pg-core";
import {user} from "@/db/schema/01_user";
import {organization} from "@/db/schema/02_organization";
import {user} from "@/db/schema/02_user";
import {organization} from "@/db/schema/03_organization";
import {relations} from "drizzle-orm";
import {createSelectSchema} from "drizzle-zod";
import {z} from "zod";
import {timestamps} from "@/db/schema/00_common";
export const member = pgTable("member", {
@@ -15,8 +16,7 @@ export const member = pgTable("member", {
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
role: text("role").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
...timestamps
});
export const memberRelations = relations(member, ({ one }) => ({
@@ -1,9 +1,10 @@
import {relations} from "drizzle-orm";
import {user} from "@/db/schema/01_user";
import {organization} from "@/db/schema/02_organization";
import {user} from "@/db/schema/02_user";
import {organization} from "@/db/schema/03_organization";
import {createSelectSchema} from "drizzle-zod";
import {z} from "zod";
import {pgTable, text, timestamp, uuid} from "drizzle-orm/pg-core";
import {timestamps} from "@/db/schema/00_common";
export const invitation = pgTable("invitation", {
@@ -18,6 +19,7 @@ export const invitation = pgTable("invitation", {
inviterId: uuid("inviter_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
...timestamps
});
@@ -1,20 +1,21 @@
import { pgTable, text, boolean, uuid, timestamp } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { Organization, organization } from "./02_organization";
import { Organization, organization } from "./03_organization";
import { createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import { Database, database } from "./06_database";
import { Database, database } from "./07_database";
import {timestamps} from "@/db/schema/00_common";
export const project = pgTable("projects", {
id: uuid("id").primaryKey().defaultRandom(),
slug: text("slug").notNull().unique(),
name: text("name").notNull().notNull(),
isArchived: boolean("is_archived").default(false),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
organizationId: uuid("organization_id")
.notNull()
.references(() => organization.id),
...timestamps
});
export const projectRelations = relations(project, ({ one, many }) => ({
@@ -1,10 +1,11 @@
import {pgTable, text, boolean, timestamp, uuid, integer, pgEnum, uniqueIndex} from "drizzle-orm/pg-core";
import {Agent, agent} from "./07_agent";
import {Project, project} from "./05_project";
import {Agent, agent} from "./08_agent";
import {Project, project} from "./06_project";
import {relations} from "drizzle-orm";
import {dbmsEnum, statusEnum} from "./types";
import {createSelectSchema} from "drizzle-zod";
import {z} from "zod";
import {timestamps} from "@/db/schema/00_common";
export const database = pgTable("databases", {
id: uuid("id").primaryKey().defaultRandom(),
@@ -15,8 +16,6 @@ export const database = pgTable("databases", {
backupPolicy: text("backup_policy"),
isWaitingForBackup: boolean("is_waiting_for_backup").default(false).notNull(),
backupToRestore: text("backup_to_restore"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
agentId: uuid("agent_id")
.notNull()
.references(() => agent.id, {onDelete: "cascade"}),
@@ -24,6 +23,7 @@ export const database = pgTable("databases", {
projectId: uuid("project_id")
.references(() => project.id),
...timestamps
});
@@ -33,11 +33,10 @@ export const backup = pgTable(
id: uuid("id").primaryKey().defaultRandom(),
status: statusEnum("status").default("waiting").notNull(),
file: text("file"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
databaseId: uuid("database_id")
.notNull()
.references(() => database.id, {onDelete: "cascade"}),
...timestamps
},
// (table) => [uniqueIndex("database_id_status_unique").on(table.databaseId, table.status)]
);
@@ -54,20 +53,19 @@ export const retentionPolicy = pgTable("retention_policies", {
gfsWeekly: integer("gfs_weekly").default(4),
gfsMonthly: integer("gfs_monthly").default(12),
gfsYearly: integer("gfs_yearly").default(3),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
...timestamps
});
export const restoration = pgTable("restorations", {
id: uuid("id").primaryKey().defaultRandom(),
status: statusEnum("status").default("waiting").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
backupId: uuid("backup_id")
.notNull()
.references(() => backup.id, {onDelete: "cascade"}),
databaseId: uuid("database_id").references(() => database.id, {onDelete: "cascade"}),
...timestamps
});
export const databaseRelations = relations(database, ({one, many}) => ({
@@ -107,6 +105,5 @@ export type DatabaseWith = Database & {
backups?: Backup[] | null;
restorations?: Restoration[] | null;
retentionPolicy?: RetentionPolicy | null;
};
@@ -1,8 +1,9 @@
import {boolean, pgTable, text, timestamp, uuid} from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import {database} from "@/db/schema/06_database";
import {database} from "@/db/schema/07_database";
import {relations} from "drizzle-orm";
import {timestamps} from "@/db/schema/00_common";
export const agent = pgTable("agents", {
id: uuid("id").primaryKey().defaultRandom(),
@@ -10,9 +11,9 @@ export const agent = pgTable("agents", {
name: text("name").notNull().notNull(),
description: text("description").notNull(),
isArchived: boolean("is_archived").default(false),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at"),
lastContact: timestamp("last_contact"),
...timestamps
});
export const agentSchema = createSelectSchema(agent);
+3
View File
@@ -0,0 +1,3 @@
export function withUpdatedAt<T extends object>(data: T): T & { updatedAt: Date } {
return {...data, updatedAt: new Date()};
}