From 3633c75c6f5b70efe221e06be10cc1973d872275 Mon Sep 17 00:00:00 2001 From: DarkSky <25152247+darkskygit@users.noreply.github.com> Date: Sat, 3 Jan 2026 03:50:14 +0800 Subject: [PATCH] feat: cleanup tables (#14203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### PR Dependency Tree * **PR #14203** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) ## Summary by CodeRabbit * **Chores** * Removed deprecated database tables, enums and schema fields (cleanup of legacy subscription, invoice, runtime settings and session expiry data). This includes irreversible data removal for those legacy elements. * **Tests** * Updated tests and test data to align with the cleaned-up schema and removed fields. ✏️ Tip: You can customize this high-level summary in your review settings. --- .../migration.sql | 38 +++++ packages/backend/server/schema.prisma | 140 +++--------------- .../server/src/__tests__/doc/history.spec.ts | 1 - .../src/__tests__/models/session.spec.ts | 1 - .../server/src/__tests__/utils/feature.ts | 1 - .../1732861452428-migrate-invite-status.ts | 18 --- .../1733125339942-universal-subscription.ts | 29 ---- .../server/src/data/migrations/index.ts | 2 - packages/backend/server/src/models/doc.ts | 1 - tests/kit/src/utils/cloud.ts | 1 - 10 files changed, 59 insertions(+), 173 deletions(-) create mode 100644 packages/backend/server/migrations/20260102181003_cleanup_table/migration.sql delete mode 100644 packages/backend/server/src/data/migrations/1732861452428-migrate-invite-status.ts delete mode 100644 packages/backend/server/src/data/migrations/1733125339942-universal-subscription.ts diff --git a/packages/backend/server/migrations/20260102181003_cleanup_table/migration.sql b/packages/backend/server/migrations/20260102181003_cleanup_table/migration.sql new file mode 100644 index 0000000000..1e502be972 --- /dev/null +++ b/packages/backend/server/migrations/20260102181003_cleanup_table/migration.sql @@ -0,0 +1,38 @@ +/* + Warnings: + + - You are about to drop the column `expires_at` on the `multiple_users_sessions` table. All the data in the column will be lost. + - You are about to drop the column `seq` on the `snapshots` table. All the data in the column will be lost. + - You are about to drop the column `seq` on the `updates` table. All the data in the column will be lost. + - You are about to drop the column `accepted` on the `workspace_user_permissions` table. All the data in the column will be lost. + - You are about to drop the `app_runtime_settings` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `user_invoices` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `user_subscriptions` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "app_runtime_settings" DROP CONSTRAINT "app_runtime_settings_last_updated_by_fkey"; + +-- AlterTable +ALTER TABLE "multiple_users_sessions" DROP COLUMN "expires_at"; + +-- AlterTable +ALTER TABLE "snapshots" DROP COLUMN "seq"; + +-- AlterTable +ALTER TABLE "updates" DROP COLUMN "seq"; + +-- AlterTable +ALTER TABLE "workspace_user_permissions" DROP COLUMN "accepted"; + +-- DropTable +DROP TABLE "app_runtime_settings"; + +-- DropTable +DROP TABLE "user_invoices"; + +-- DropTable +DROP TABLE "user_subscriptions"; + +-- DropEnum +DROP TYPE "RuntimeConfigType"; diff --git a/packages/backend/server/schema.prisma b/packages/backend/server/schema.prisma index 56add0af0b..4057471c3a 100644 --- a/packages/backend/server/schema.prisma +++ b/packages/backend/server/schema.prisma @@ -25,31 +25,29 @@ model User { registered Boolean @default(true) disabled Boolean @default(false) - features UserFeature[] - userStripeCustomer UserStripeCustomer? - workspaces WorkspaceUserRole[] + features UserFeature[] + userStripeCustomer UserStripeCustomer? + workspaces WorkspaceUserRole[] // Invite others to join the workspace - WorkspaceInvitations WorkspaceUserRole[] @relation("inviter") - docPermissions WorkspaceDocUserRole[] - connectedAccounts ConnectedAccount[] - sessions UserSession[] - aiSessions AiSession[] - /// @deprecated - deprecatedAppRuntimeSettings DeprecatedAppRuntimeSettings[] - appConfigs AppConfig[] - userSnapshots UserSnapshot[] - createdSnapshot Snapshot[] @relation("createdSnapshot") - updatedSnapshot Snapshot[] @relation("updatedSnapshot") - createdUpdate Update[] @relation("createdUpdate") - createdHistory SnapshotHistory[] @relation("createdHistory") - createdAiJobs AiJobs[] @relation("createdAiJobs") + WorkspaceInvitations WorkspaceUserRole[] @relation("inviter") + docPermissions WorkspaceDocUserRole[] + connectedAccounts ConnectedAccount[] + sessions UserSession[] + aiSessions AiSession[] + appConfigs AppConfig[] + userSnapshots UserSnapshot[] + createdSnapshot Snapshot[] @relation("createdSnapshot") + updatedSnapshot Snapshot[] @relation("updatedSnapshot") + createdUpdate Update[] @relation("createdUpdate") + createdHistory SnapshotHistory[] @relation("createdHistory") + createdAiJobs AiJobs[] @relation("createdAiJobs") // receive notifications - notifications Notification[] @relation("user_notifications") - settings UserSettings? - comments Comment[] - replies Reply[] - commentAttachments CommentAttachment[] @relation("createdCommentAttachments") - AccessToken AccessToken[] + notifications Notification[] @relation("user_notifications") + settings UserSettings? + comments Comment[] + replies Reply[] + commentAttachments CommentAttachment[] @relation("createdCommentAttachments") + AccessToken AccessToken[] @@index([email]) @@map("users") @@ -79,9 +77,6 @@ model Session { createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) userSessions UserSession[] - // @deprecated use [UserSession.expiresAt] - deprecated_expiresAt DateTime? @map("expires_at") @db.Timestamptz(3) - @@map("multiple_users_sessions") } @@ -207,9 +202,6 @@ model WorkspaceUserRole { workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) inviter User? @relation(name: "inviter", fields: [inviterId], references: [id], onDelete: SetNull) - /// @deprecated Whether the permission invitation is accepted by the user, use status instead - accepted Boolean @default(false) - @@unique([workspaceId, userId]) // optimize for querying user's workspace permissions @@index([workspaceId, type, status]) @@ -329,9 +321,6 @@ model Snapshot { createdByUser User? @relation(name: "createdSnapshot", fields: [createdBy], references: [id], onDelete: SetNull) updatedByUser User? @relation(name: "updatedSnapshot", fields: [updatedBy], references: [id], onDelete: SetNull) - // @deprecated use updatedAt only - seq Int? @default(0) @db.Integer - // we need to clear all hanging updates and snapshots before enable the foreign key on workspaceId // workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) @@ -369,9 +358,6 @@ model Update { // will delete creator record if creator's account is deleted createdByUser User? @relation(name: "createdUpdate", fields: [createdBy], references: [id], onDelete: SetNull) - // @deprecated use createdAt only - seq Int? @db.Integer - @@id([workspaceId, id, createdAt]) @@map("updates") } @@ -645,32 +631,6 @@ model DataMigration { @@map("_data_migrations") } -enum RuntimeConfigType { - String - Number - Boolean - Object - Array -} - -/// @deprecated use AppConfig instead -model DeprecatedAppRuntimeSettings { - id String @id @db.VarChar - type RuntimeConfigType - module String @db.VarChar - key String @db.VarChar - value Json @db.Json - description String @db.Text - updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) - deletedAt DateTime? @map("deleted_at") @db.Timestamptz(3) - lastUpdatedBy String? @map("last_updated_by") @db.VarChar - - lastUpdatedByUser User? @relation(fields: [lastUpdatedBy], references: [id]) - - @@unique([module, key]) - @@map("app_runtime_settings") -} - model AppConfig { id String @id @db.VarChar value Json @db.JsonB @@ -683,64 +643,6 @@ model AppConfig { @@map("app_configs") } -model DeprecatedUserSubscription { - id Int @id @default(autoincrement()) @db.Integer - userId String @map("user_id") @db.VarChar - plan String @db.VarChar(20) - // yearly/monthly/lifetime - recurring String @db.VarChar(20) - // onetime subscription or anything else - variant String? @db.VarChar(20) - // subscription.id, null for lifetime payment or one time payment subscription - stripeSubscriptionId String? @unique @map("stripe_subscription_id") - // subscription.status, active/past_due/canceled/unpaid... - status String @db.VarChar(20) - // subscription.current_period_start - start DateTime @map("start") @db.Timestamptz(3) - // subscription.current_period_end, null for lifetime payment - end DateTime? @map("end") @db.Timestamptz(3) - // subscription.billing_cycle_anchor - nextBillAt DateTime? @map("next_bill_at") @db.Timestamptz(3) - // subscription.canceled_at - canceledAt DateTime? @map("canceled_at") @db.Timestamptz(3) - // subscription.trial_start - trialStart DateTime? @map("trial_start") @db.Timestamptz(3) - // subscription.trial_end - trialEnd DateTime? @map("trial_end") @db.Timestamptz(3) - stripeScheduleId String? @map("stripe_schedule_id") @db.VarChar - - createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) - updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) - - @@unique([userId, plan]) - @@map("user_subscriptions") -} - -model DeprecatedUserInvoice { - id Int @id @default(autoincrement()) @db.Integer - userId String @map("user_id") @db.VarChar - stripeInvoiceId String @unique @map("stripe_invoice_id") - currency String @db.VarChar(3) - // CNY 12.50 stored as 1250 - amount Int @db.Integer - status String @db.VarChar(20) - createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) - updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) - // billing reason - reason String? @db.VarChar - lastPaymentError String? @map("last_payment_error") @db.Text - // stripe hosted invoice link - link String? @db.Text - - // @deprecated - plan String? @db.VarChar(20) - // @deprecated - recurring String? @db.VarChar(20) - - @@index([userId]) - @@map("user_invoices") -} - model UserStripeCustomer { userId String @id @map("user_id") @db.VarChar stripeCustomerId String @unique @map("stripe_customer_id") @db.VarChar diff --git a/packages/backend/server/src/__tests__/doc/history.spec.ts b/packages/backend/server/src/__tests__/doc/history.spec.ts index eae00aae8c..7aa15002c2 100644 --- a/packages/backend/server/src/__tests__/doc/history.spec.ts +++ b/packages/backend/server/src/__tests__/doc/history.spec.ts @@ -41,7 +41,6 @@ const snapshot: Snapshot = { id: 'doc1', blob: Uint8Array.from([1, 0]), state: Uint8Array.from([0]), - seq: 0, size: BigInt(2), updatedAt: new Date(), createdAt: new Date(), diff --git a/packages/backend/server/src/__tests__/models/session.spec.ts b/packages/backend/server/src/__tests__/models/session.spec.ts index 66630b2f6a..bf11545036 100644 --- a/packages/backend/server/src/__tests__/models/session.spec.ts +++ b/packages/backend/server/src/__tests__/models/session.spec.ts @@ -38,7 +38,6 @@ test('should create a new session', async t => { const session = await t.context.session.createSession(); t.truthy(session.id); t.truthy(session.createdAt); - t.is(session.deprecated_expiresAt, null); }); test('should get a exists session', async t => { diff --git a/packages/backend/server/src/__tests__/utils/feature.ts b/packages/backend/server/src/__tests__/utils/feature.ts index c345a9df8e..1eed73a03d 100644 --- a/packages/backend/server/src/__tests__/utils/feature.ts +++ b/packages/backend/server/src/__tests__/utils/feature.ts @@ -16,7 +16,6 @@ export class WorkspaceResolverMock { create: { type: WorkspaceRole.Owner, userId: user.id, - accepted: true, status: WorkspaceMemberStatus.Accepted, }, }, diff --git a/packages/backend/server/src/data/migrations/1732861452428-migrate-invite-status.ts b/packages/backend/server/src/data/migrations/1732861452428-migrate-invite-status.ts deleted file mode 100644 index 2cbc0136f1..0000000000 --- a/packages/backend/server/src/data/migrations/1732861452428-migrate-invite-status.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { PrismaClient, WorkspaceMemberStatus } from '@prisma/client'; - -export class MigrateInviteStatus1732861452428 { - // do the migration - static async up(db: PrismaClient) { - await db.workspaceUserRole.updateMany({ - where: { - accepted: true, - }, - data: { - status: WorkspaceMemberStatus.Accepted, - }, - }); - } - - // revert the migration - static async down(_db: PrismaClient) {} -} diff --git a/packages/backend/server/src/data/migrations/1733125339942-universal-subscription.ts b/packages/backend/server/src/data/migrations/1733125339942-universal-subscription.ts deleted file mode 100644 index 2cf3fcf6f0..0000000000 --- a/packages/backend/server/src/data/migrations/1733125339942-universal-subscription.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -import { loop } from './utils/loop'; - -export class UniversalSubscription1733125339942 { - // do the migration - static async up(db: PrismaClient) { - await loop(async (offset, take) => { - const oldSubscriptions = await db.deprecatedUserSubscription.findMany({ - skip: offset, - take, - }); - - await db.subscription.createMany({ - data: oldSubscriptions.map(({ userId, ...subscription }) => ({ - targetId: userId, - ...subscription, - })), - }); - - return oldSubscriptions.length; - }, 50); - } - - // revert the migration - static async down(_db: PrismaClient) { - // noop - } -} diff --git a/packages/backend/server/src/data/migrations/index.ts b/packages/backend/server/src/data/migrations/index.ts index a32a497498..98e629bf51 100644 --- a/packages/backend/server/src/data/migrations/index.ts +++ b/packages/backend/server/src/data/migrations/index.ts @@ -1,7 +1,5 @@ export * from './1698398506533-guid'; export * from './1703756315970-unamed-account'; export * from './1721299086340-refresh-unnamed-user'; -export * from './1732861452428-migrate-invite-status'; -export * from './1733125339942-universal-subscription'; export * from './1745211351719-create-indexer-tables'; export * from './1751966744168-correct-session-update-time'; diff --git a/packages/backend/server/src/models/doc.ts b/packages/backend/server/src/models/doc.ts index ab3f68c7ee..db1a7530b5 100644 --- a/packages/backend/server/src/models/doc.ts +++ b/packages/backend/server/src/models/doc.ts @@ -61,7 +61,6 @@ export class DocModel extends BaseModel { blob: record.blob, createdAt: new Date(record.timestamp), createdBy: record.editorId || null, - seq: null, }; } diff --git a/tests/kit/src/utils/cloud.ts b/tests/kit/src/utils/cloud.ts index 5e44fcc229..0f3f7da33c 100644 --- a/tests/kit/src/utils/cloud.ts +++ b/tests/kit/src/utils/cloud.ts @@ -92,7 +92,6 @@ export async function addUserToWorkspace( data: { workspaceId: workspace.id, userId, - accepted: true, status: 'Accepted', type: permission, },