+
+
+
+
+
+
+
+ Are you absolutely sure to delete base?
+
+ This action cannot be undone. This will permanently delete your database state and remove your data from our
+ servers.
+
+
+
+
Please type DELETE to confirm.
+
+
+
+ Cancel
+
+
+
+
+
+
+
diff --git a/packages/base/src/dto/delete-base.dto.ts b/packages/base/src/dto/delete-base.dto.ts
new file mode 100644
index 000000000..062f9595c
--- /dev/null
+++ b/packages/base/src/dto/delete-base.dto.ts
@@ -0,0 +1,8 @@
+import { z } from "@undb/zod"
+import { baseIdSchema } from "../value-objects"
+
+export const deleteBaseDTO = z.object({
+ id: baseIdSchema,
+})
+
+export type IDeleteBaseDTO = z.infer
diff --git a/packages/base/src/dto/index.ts b/packages/base/src/dto/index.ts
index 6e164a7d2..185736b43 100644
--- a/packages/base/src/dto/index.ts
+++ b/packages/base/src/dto/index.ts
@@ -1,4 +1,5 @@
export * from "./base.dto"
export * from "./create-base.dto"
+export * from "./delete-base.dto"
export * from "./duplicate-base.dto"
export * from "./update-base.dto"
diff --git a/packages/command-handlers/src/handlers/delete-base.command-handler.ts b/packages/command-handlers/src/handlers/delete-base.command-handler.ts
new file mode 100644
index 000000000..4446558cc
--- /dev/null
+++ b/packages/command-handlers/src/handlers/delete-base.command-handler.ts
@@ -0,0 +1,22 @@
+import { injectBaseRepository, type IBaseRepository } from "@undb/base"
+import { DeleteBaseCommand } from "@undb/commands"
+import { commandHandler } from "@undb/cqrs"
+import { singleton } from "@undb/di"
+import { type ICommandHandler } from "@undb/domain"
+
+@commandHandler(DeleteBaseCommand)
+@singleton()
+export class DeleteBaseCommandHandler implements ICommandHandler {
+ constructor(
+ @injectBaseRepository()
+ private readonly repository: IBaseRepository,
+ ) {}
+
+ async execute(command: DeleteBaseCommand): Promise {
+ const base = (await this.repository.findOneById(command.id)).expect("base not found")
+
+ await this.repository.deleteOneById(base.id.value)
+
+ return base.id.value
+ }
+}
diff --git a/packages/command-handlers/src/handlers/duplicate-base.command-handler.ts b/packages/command-handlers/src/handlers/duplicate-base.command-handler.ts
index 069d8290b..a40bd04e7 100644
--- a/packages/command-handlers/src/handlers/duplicate-base.command-handler.ts
+++ b/packages/command-handlers/src/handlers/duplicate-base.command-handler.ts
@@ -22,7 +22,8 @@ export class DuplicateBaseCommandHandler implements ICommandHandler {
const base = (await this.baseRepository.findOneById(command.id)).expect("Base not found")
- const duplicatedBase = await this.tableService.duplicateBase(base, mustGetCurrentSpaceId(), command)
+ const spaceId = mustGetCurrentSpaceId()
+ const duplicatedBase = await this.tableService.duplicateBase(base, spaceId, spaceId, command)
return duplicatedBase.id.value
}
diff --git a/packages/command-handlers/src/handlers/index.ts b/packages/command-handlers/src/handlers/index.ts
index 74dd354b8..0efb8ed5c 100644
--- a/packages/command-handlers/src/handlers/index.ts
+++ b/packages/command-handlers/src/handlers/index.ts
@@ -13,6 +13,7 @@ import { CreateTableFormCommandHandler } from "./create-table-form.command-handl
import { CreateTableViewCommandHandler } from "./create-table-view.command-handler"
import { CreateTableCommandHandler } from "./create-table.command-handler"
import { CreateWebhookCommandHandler } from "./create-webhook.command-handler"
+import { DeleteBaseCommandHandler } from "./delete-base.command-handler"
import { DeleteInvitationCommandHandler } from "./delete-invitation.command-handler"
import { DeleteRecordCommandHandler } from "./delete-record.command-handler"
import { DeleteSpaceCommandHandler } from "./delete-space.command-handler"
@@ -94,4 +95,5 @@ export const commandHandlers = [
DeleteWebhookCommandHandler,
DuplicateTableCommandHandler,
DuplicateBaseCommandHandler,
+ DeleteBaseCommandHandler,
]
diff --git a/packages/commands/src/delete-base.command.ts b/packages/commands/src/delete-base.command.ts
new file mode 100644
index 000000000..526c9d1f3
--- /dev/null
+++ b/packages/commands/src/delete-base.command.ts
@@ -0,0 +1,16 @@
+import { deleteBaseDTO } from "@undb/base"
+import { Command, type CommandProps } from "@undb/domain"
+import { z } from "@undb/zod"
+
+export const deleteBaseCommand = deleteBaseDTO
+
+export type IDeleteBaseCommand = z.infer
+
+export class DeleteBaseCommand extends Command implements IDeleteBaseCommand {
+ public readonly id: string
+
+ constructor(props: CommandProps) {
+ super(props)
+ this.id = props.id
+ }
+}
diff --git a/packages/commands/src/index.ts b/packages/commands/src/index.ts
index 914f77d84..91cd96093 100644
--- a/packages/commands/src/index.ts
+++ b/packages/commands/src/index.ts
@@ -13,6 +13,7 @@ export * from "./create-table-form.command"
export * from "./create-table-view.command"
export * from "./create-table.command"
export * from "./create-webhook.command"
+export * from "./delete-base.command"
export * from "./delete-invitation.command"
export * from "./delete-record.command"
export * from "./delete-space.command"
diff --git a/packages/persistence/src/base/base.repository.ts b/packages/persistence/src/base/base.repository.ts
index dcce8443f..b81d572fb 100644
--- a/packages/persistence/src/base/base.repository.ts
+++ b/packages/persistence/src/base/base.repository.ts
@@ -1,7 +1,7 @@
import {
+ injectBaseOutboxService,
WithBaseId,
WithBaseSpaceId,
- injectBaseOutboxService,
type Base,
type IBaseOutboxService,
type IBaseRepository,
@@ -10,9 +10,11 @@ import {
import { executionContext, mustGetCurrentSpaceId } from "@undb/context/server"
import { inject, singleton } from "@undb/di"
import { None, Some, type Option } from "@undb/domain"
+import { injectTableRepository, TableBaseIdSpecification, type ITableRepository } from "@undb/table"
import { getCurrentTransaction } from "../ctx"
import type { IQueryBuilder } from "../qb"
import { injectQueryBuilder } from "../qb.provider"
+import { UnderlyingTableService } from "../underlying/underlying-table.service"
import { BaseFilterVisitor } from "./base.filter-visitor"
import { BaseMapper } from "./base.mapper"
import { BaseMutateVisitor } from "./base.mutate-visitor"
@@ -26,6 +28,10 @@ export class BaseRepository implements IBaseRepository {
private readonly outboxService: IBaseOutboxService,
@injectQueryBuilder()
private readonly qb: IQueryBuilder,
+ @injectTableRepository()
+ private readonly tableRepository: ITableRepository,
+ @inject(UnderlyingTableService)
+ private readonly underlyingTableService: UnderlyingTableService,
) {}
async find(spec: IBaseSpecification): Promise {
@@ -101,7 +107,37 @@ export class BaseRepository implements IBaseRepository {
await this.outboxService.save(base)
}
- deleteOneById(id: string): Promise {
- throw new Error("Method not implemented.")
+ async deleteOneById(id: string): Promise {
+ const trx = getCurrentTransaction()
+
+ const tables = await this.tableRepository.find(Some(new TableBaseIdSpecification(id)))
+ const tableIds = tables.map((t) => t.id.value)
+
+ await trx
+ .deleteFrom("undb_table_id_mapping")
+ .where((eb) => eb.eb("table_id", "in", tableIds))
+ .execute()
+
+ await trx
+ .deleteFrom("undb_rollup_id_mapping")
+ .where((eb) => eb.eb("table_id", "in", tableIds))
+ .execute()
+
+ await trx
+ .deleteFrom("undb_reference_id_mapping")
+ .where((eb) => eb.eb("table_id", "in", tableIds))
+ .execute()
+
+ await trx
+ .deleteFrom("undb_table")
+ .where((eb) => eb.eb("id", "in", tableIds))
+ .execute()
+
+ await trx
+ .deleteFrom("undb_base")
+ .where((eb) => eb.eb("id", "=", id))
+ .execute()
+
+ await this.underlyingTableService.deleteTables(tables)
}
}
diff --git a/packages/persistence/src/underlying/underlying-table.service.ts b/packages/persistence/src/underlying/underlying-table.service.ts
index 3504da735..825812898 100644
--- a/packages/persistence/src/underlying/underlying-table.service.ts
+++ b/packages/persistence/src/underlying/underlying-table.service.ts
@@ -3,6 +3,7 @@ import { createLogger } from "@undb/logger"
import type { TableComositeSpecification, TableDo } from "@undb/table"
import type { CompiledQuery } from "kysely"
import { getAnonymousTransaction, getCurrentTransaction } from "../ctx"
+import { JoinTable } from "./reference/join-table"
import { UnderlyingTable } from "./underlying-table"
import { UnderlyingTableFieldVisitor } from "./underlying-table-field.visitor"
import { UnderlyingTableSpecVisitor } from "./underlying-table-spec.visitor"
@@ -46,5 +47,16 @@ export class UnderlyingTableService {
const t = new UnderlyingTable(table)
const trx = getCurrentTransaction()
await trx.schema.dropTable(t.name).execute()
+ const referenceFields = table.schema.getReferenceFields()
+ for (const field of referenceFields) {
+ const joinTable = new JoinTable(table, field)
+ await trx.schema.dropTable(joinTable.getTableName()).execute()
+ }
+ }
+
+ async deleteTables(tables: TableDo[]) {
+ for (const table of tables) {
+ await this.delete(table)
+ }
}
}
diff --git a/packages/trpc/src/router.ts b/packages/trpc/src/router.ts
index ac0a73db2..121772bb6 100644
--- a/packages/trpc/src/router.ts
+++ b/packages/trpc/src/router.ts
@@ -13,6 +13,7 @@ import {
CreateTableFormCommand,
CreateTableViewCommand,
CreateWebhookCommand,
+ DeleteBaseCommand,
DeleteInvitationCommand,
DeleteRecordCommand,
DeleteTableCommand,
@@ -58,6 +59,7 @@ import {
createTableFormCommand,
createTableViewCommand,
createWebhookCommand,
+ deleteBaseCommand,
deleteInvitationCommand,
deleteRecordCommand,
deleteTableCommand,
@@ -322,6 +324,10 @@ const baseRouter = t.router({
.use(authz("base:update"))
.input(updateBaseCommand)
.mutation(({ input }) => commandBus.execute(new UpdateBaseCommand(input))),
+ delete: privateProcedure
+ .use(authz("base:delete"))
+ .input(deleteBaseCommand)
+ .mutation(({ input }) => commandBus.execute(new DeleteBaseCommand(input))),
})
const shareRouter = t.router({