-- CreateTable CREATE TABLE "tools" ( "id" TEXT NOT NULL PRIMARY KEY, "name" TEXT NOT NULL, "slug" TEXT NOT NULL, "category_id" TEXT NOT NULL, "description" TEXT NOT NULL, "rating" REAL NOT NULL DEFAULT 0, "download_count" INTEGER NOT NULL DEFAULT 0, "open_count" INTEGER NOT NULL DEFAULT 0, "access_mode" TEXT NOT NULL DEFAULT 'download', "open_url" TEXT, "open_in_new_tab" BOOLEAN NOT NULL DEFAULT true, "latest_artifact_id" TEXT, "status" TEXT NOT NULL DEFAULT 'draft', "updated_at" TEXT NOT NULL, "is_deleted" BOOLEAN NOT NULL DEFAULT false, "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, "modified_at" DATETIME NOT NULL, CONSTRAINT "tools_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "categories" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT "tools_latest_artifact_id_fkey" FOREIGN KEY ("latest_artifact_id") REFERENCES "tool_artifacts" ("id") ON DELETE SET NULL ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "tool_artifacts" ( "id" TEXT NOT NULL PRIMARY KEY, "tool_id" TEXT NOT NULL, "version" TEXT NOT NULL, "file_name" TEXT NOT NULL, "file_size_bytes" INTEGER NOT NULL, "sha256" TEXT NOT NULL, "mime_type" TEXT, "gitlab_project_id" INTEGER NOT NULL, "gitlab_package_name" TEXT NOT NULL, "gitlab_package_version" TEXT NOT NULL, "gitlab_file_path" TEXT NOT NULL, "status" TEXT NOT NULL DEFAULT 'active', "release_notes" TEXT, "uploaded_by" TEXT, "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "tool_artifacts_tool_id_fkey" FOREIGN KEY ("tool_id") REFERENCES "tools" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT "tool_artifacts_uploaded_by_fkey" FOREIGN KEY ("uploaded_by") REFERENCES "admin_users" ("id") ON DELETE SET NULL ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "categories" ( "id" TEXT NOT NULL PRIMARY KEY, "name" TEXT NOT NULL, "sort_order" INTEGER NOT NULL DEFAULT 100, "is_deleted" BOOLEAN NOT NULL DEFAULT false ); -- CreateTable CREATE TABLE "tags" ( "id" TEXT NOT NULL PRIMARY KEY, "name" TEXT NOT NULL, "is_deleted" BOOLEAN NOT NULL DEFAULT false ); -- CreateTable CREATE TABLE "tool_tags" ( "tool_id" TEXT NOT NULL, "tag_id" TEXT NOT NULL, PRIMARY KEY ("tool_id", "tag_id"), CONSTRAINT "tool_tags_tool_id_fkey" FOREIGN KEY ("tool_id") REFERENCES "tools" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "tool_tags_tag_id_fkey" FOREIGN KEY ("tag_id") REFERENCES "tags" ("id") ON DELETE CASCADE ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "tool_features" ( "id" TEXT NOT NULL PRIMARY KEY, "tool_id" TEXT NOT NULL, "feature_text" TEXT NOT NULL, "sort_order" INTEGER NOT NULL DEFAULT 100, CONSTRAINT "tool_features_tool_id_fkey" FOREIGN KEY ("tool_id") REFERENCES "tools" ("id") ON DELETE CASCADE ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "hot_keywords" ( "id" TEXT NOT NULL PRIMARY KEY, "keyword" TEXT NOT NULL, "sort_order" INTEGER NOT NULL DEFAULT 100, "is_active" BOOLEAN NOT NULL DEFAULT true ); -- CreateTable CREATE TABLE "download_tickets" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "ticket" TEXT NOT NULL, "tool_id" TEXT NOT NULL, "artifact_id" TEXT NOT NULL, "channel" TEXT, "client_version" TEXT, "request_ip" TEXT, "expires_at" DATETIME NOT NULL, "consumed_at" DATETIME, "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "download_tickets_tool_id_fkey" FOREIGN KEY ("tool_id") REFERENCES "tools" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT "download_tickets_artifact_id_fkey" FOREIGN KEY ("artifact_id") REFERENCES "tool_artifacts" ("id") ON DELETE RESTRICT ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "download_records" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "tool_id" TEXT NOT NULL, "artifact_id" TEXT NOT NULL, "ticket" TEXT, "downloaded_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, "client_ip" TEXT, "user_agent" TEXT, "channel" TEXT, "client_version" TEXT, "status" TEXT NOT NULL DEFAULT 'success', "error_message" TEXT, CONSTRAINT "download_records_tool_id_fkey" FOREIGN KEY ("tool_id") REFERENCES "tools" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT "download_records_artifact_id_fkey" FOREIGN KEY ("artifact_id") REFERENCES "tool_artifacts" ("id") ON DELETE RESTRICT ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "open_records" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "tool_id" TEXT NOT NULL, "opened_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, "client_ip" TEXT, "user_agent" TEXT, "channel" TEXT, "client_version" TEXT, "referer" TEXT, CONSTRAINT "open_records_tool_id_fkey" FOREIGN KEY ("tool_id") REFERENCES "tools" ("id") ON DELETE RESTRICT ON UPDATE CASCADE ); -- CreateTable CREATE TABLE "admin_users" ( "id" TEXT NOT NULL PRIMARY KEY, "username" TEXT NOT NULL, "password_hash" TEXT NOT NULL, "display_name" TEXT, "status" TEXT NOT NULL DEFAULT 'active', "last_login_at" DATETIME, "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, "modified_at" DATETIME NOT NULL ); -- CreateTable CREATE TABLE "admin_audit_logs" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "admin_user_id" TEXT, "action" TEXT NOT NULL, "resource_type" TEXT NOT NULL, "resource_id" TEXT, "request_method" TEXT NOT NULL, "request_path" TEXT NOT NULL, "request_body" TEXT, "ip" TEXT, "user_agent" TEXT, "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "admin_audit_logs_admin_user_id_fkey" FOREIGN KEY ("admin_user_id") REFERENCES "admin_users" ("id") ON DELETE SET NULL ON UPDATE CASCADE ); -- CreateIndex CREATE UNIQUE INDEX "tools_slug_key" ON "tools"("slug"); -- CreateIndex CREATE INDEX "idx_tools_category_id" ON "tools"("category_id"); -- CreateIndex CREATE INDEX "idx_tools_status" ON "tools"("status"); -- CreateIndex CREATE INDEX "idx_tools_access_mode" ON "tools"("access_mode"); -- CreateIndex CREATE INDEX "idx_tools_download_count" ON "tools"("download_count"); -- CreateIndex CREATE INDEX "idx_tools_open_count" ON "tools"("open_count"); -- CreateIndex CREATE INDEX "idx_tools_updated_at" ON "tools"("updated_at"); -- CreateIndex CREATE INDEX "idx_tools_rating" ON "tools"("rating"); -- CreateIndex CREATE INDEX "idx_tools_name" ON "tools"("name"); -- CreateIndex CREATE INDEX "idx_artifact_tool_id" ON "tool_artifacts"("tool_id"); -- CreateIndex CREATE INDEX "idx_artifact_status" ON "tool_artifacts"("status"); -- CreateIndex CREATE UNIQUE INDEX "uk_tool_version" ON "tool_artifacts"("tool_id", "version"); -- CreateIndex CREATE UNIQUE INDEX "categories_name_key" ON "categories"("name"); -- CreateIndex CREATE UNIQUE INDEX "tags_name_key" ON "tags"("name"); -- CreateIndex CREATE INDEX "idx_tool_feature_tool_id" ON "tool_features"("tool_id"); -- CreateIndex CREATE UNIQUE INDEX "hot_keywords_keyword_key" ON "hot_keywords"("keyword"); -- CreateIndex CREATE UNIQUE INDEX "download_tickets_ticket_key" ON "download_tickets"("ticket"); -- CreateIndex CREATE INDEX "idx_download_tickets_tool_id" ON "download_tickets"("tool_id"); -- CreateIndex CREATE INDEX "idx_download_tickets_expires_at" ON "download_tickets"("expires_at"); -- CreateIndex CREATE INDEX "idx_download_records_tool_id" ON "download_records"("tool_id"); -- CreateIndex CREATE INDEX "idx_download_records_artifact_id" ON "download_records"("artifact_id"); -- CreateIndex CREATE INDEX "idx_open_records_tool_id" ON "open_records"("tool_id"); -- CreateIndex CREATE UNIQUE INDEX "admin_users_username_key" ON "admin_users"("username"); -- CreateIndex CREATE INDEX "idx_admin_audit_logs_user_id" ON "admin_audit_logs"("admin_user_id");