Files
tool-evaluator/lib/db/src/schema/tools.ts
T
opencode 2f20b1e5c2
Build & Push Docker Image / build (push) Successful in 2m15s
feat: trash (soft delete) with admin tool management
- tools: add deletedAt/deletedBy, soft delete via DELETE /tools/:id when
  actor has trash entitlement, else immediate hard delete
- trash endpoints: GET /tools/trash, POST /tools/trash (admin bulk),
  POST /tools/trash/restore, DELETE /tools/trash, POST /tools/trash/empty
- trash feature for premium/enterprise; exclude trashed from all public
  surfaces (browse, categories, features, tags, similar, ratings, costs,
  analytics, redundancy)
- TRASH_RETENTION_DAYS env (0 = keep forever) with hourly purge job
- frontend: /trash page (premium+, restore for all, permanent delete +
  empty for admin), admin Tools tab with multi-select bulk trash,
  sidebar Trash link, tool-detail delete hint
2026-08-02 02:02:16 +02:00

24 lines
1.1 KiB
TypeScript

import { pgTable, text, serial, timestamp } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod/v4";
export const toolsTable = pgTable("tools", {
id: serial("id").primaryKey(),
name: text("name").notNull(),
description: text("description").notNull(),
category: text("category").notNull(),
websiteUrl: text("website_url"),
iconUrl: text("icon_url"),
createdBy: text("created_by"),
features: text("features").array().notNull().default([]),
tags: text("tags").array().notNull().default([]),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => new Date()),
deletedAt: timestamp("deleted_at", { withTimezone: true }),
deletedBy: text("deleted_by"),
});
export const insertToolSchema = createInsertSchema(toolsTable).omit({ id: true, createdAt: true, updatedAt: true });
export type InsertTool = z.infer<typeof insertToolSchema>;
export type Tool = typeof toolsTable.$inferSelect;