IKHSAN
EN Read in EnglishID

homeio

Publik

Fork dari doctor-io/homeio

Branch
main
Commit terakhir
958d74616 Oktober 2026

trash-repository.ts

Buka raw
import "server-only";

import { eq, sql } from "drizzle-orm";
import { db } from "@/lib/server/db/drizzle";
import { filesTrashEntries } from "@/lib/server/db/schema";

export type TrashEntryRecord = {
  id: string;
  trashPath: string;
  originalPath: string;
  deletedAt: Date;
};

export type UpsertTrashEntryInput = {
  id: string;
  trashPath: string;
  originalPath: string;
  deletedAt?: Date;
};

let ensureTrashEntriesTablePromise: Promise<void> | null = null;

async function ensureTrashEntriesTable() {
  if (!ensureTrashEntriesTablePromise) {
    ensureTrashEntriesTablePromise = (async () => {
      await db.execute(sql`
        CREATE TABLE IF NOT EXISTS files_trash_entries (
          id text PRIMARY KEY,
          trash_path text NOT NULL,
          original_path text NOT NULL,
          deleted_at timestamptz NOT NULL DEFAULT NOW()
        )
      `);
      await db.execute(sql`
        CREATE UNIQUE INDEX IF NOT EXISTS files_trash_entries_trash_path_idx
        ON files_trash_entries (trash_path)
      `);
      await db.execute(sql`
        CREATE INDEX IF NOT EXISTS files_trash_entries_deleted_at_idx
        ON files_trash_entries (deleted_at DESC)
      `);
    })().catch((error) => {
      ensureTrashEntriesTablePromise = null;
      throw error;
    });
  }

  await ensureTrashEntriesTablePromise;
}

function toRecord(row: {
  id: string;
  trashPath: string;
  originalPath: string;
  deletedAt: Date;
}): TrashEntryRecord {
  return {
    id: row.id,
    trashPath: row.trashPath,
    originalPath: row.originalPath,
    deletedAt: row.deletedAt,
  };
}

export async function upsertTrashEntryInDb(input: UpsertTrashEntryInput) {
  await ensureTrashEntriesTable();

  const deletedAt = input.deletedAt ?? new Date();

  const rows = await db
    .insert(filesTrashEntries)
    .values({
      id: input.id,
      trashPath: input.trashPath,
      originalPath: input.originalPath,
      deletedAt,
    })
    .onConflictDoUpdate({
      target: filesTrashEntries.trashPath,
      set: {
        originalPath: input.originalPath,
        deletedAt,
      },
    })
    .returning({
      id: filesTrashEntries.id,
      trashPath: filesTrashEntries.trashPath,
      originalPath: filesTrashEntries.originalPath,
      deletedAt: filesTrashEntries.deletedAt,
    });

  if (!rows[0]) {
    throw new Error("Failed to upsert trash entry");
  }

  return toRecord(rows[0]);
}

export async function getTrashEntryFromDb(trashPath: string) {
  await ensureTrashEntriesTable();

  const rows = await db
    .select({
      id: filesTrashEntries.id,
      trashPath: filesTrashEntries.trashPath,
      originalPath: filesTrashEntries.originalPath,
      deletedAt: filesTrashEntries.deletedAt,
    })
    .from(filesTrashEntries)
    .where(eq(filesTrashEntries.trashPath, trashPath))
    .limit(1);

  return rows[0] ? toRecord(rows[0]) : null;
}

export async function deleteTrashEntryFromDb(trashPath: string) {
  await ensureTrashEntriesTable();

  const rows = await db
    .delete(filesTrashEntries)
    .where(eq(filesTrashEntries.trashPath, trashPath))
    .returning({
      id: filesTrashEntries.id,
      trashPath: filesTrashEntries.trashPath,
      originalPath: filesTrashEntries.originalPath,
      deletedAt: filesTrashEntries.deletedAt,
    });

  return rows[0] ? toRecord(rows[0]) : null;
}

export async function listTrashEntriesFromDb() {
  await ensureTrashEntriesTable();

  const rows = await db
    .select({
      id: filesTrashEntries.id,
      trashPath: filesTrashEntries.trashPath,
      originalPath: filesTrashEntries.originalPath,
      deletedAt: filesTrashEntries.deletedAt,
    })
    .from(filesTrashEntries);

  return rows.map(toRecord);
}

export async function deleteAllTrashEntriesFromDb() {
  await ensureTrashEntriesTable();

  const rows = await db
    .delete(filesTrashEntries)
    .returning({
      id: filesTrashEntries.id,
      trashPath: filesTrashEntries.trashPath,
      originalPath: filesTrashEntries.originalPath,
      deletedAt: filesTrashEntries.deletedAt,
    });

  return rows.map(toRecord);
}
byte
4.090
baris
161
Jenis
ts
Commit terakhir
16 Oktober 2026