| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.buildsRouter = buildsRouter;
- const express_1 = require("express");
- const uuid_1 = require("uuid");
- const path_1 = __importDefault(require("path"));
- const fs_1 = __importDefault(require("fs"));
- const buildService_1 = require("../services/buildService");
- function buildsRouter(db, storageDir, onThemeSaved) {
- const router = (0, express_1.Router)();
- const buildService = new buildService_1.BuildService(db, storageDir);
- // POST /api/v1/creatives/:id/builds — 触发构建
- router.post("/creatives/:id/builds", async (req, res) => {
- try {
- const { id } = req.params;
- const { platforms, theme } = req.body;
- if (!platforms || !Array.isArray(platforms) || platforms.length === 0) {
- res.status(400).json({
- error: { message: "platforms must be a non-empty array" },
- });
- return;
- }
- const creative = db
- .prepare("SELECT * FROM creatives WHERE id = ?")
- .get(id);
- if (!creative) {
- res.status(404).json({ error: { message: "Creative not found" } });
- return;
- }
- if (creative.status === "draft") {
- res.status(400).json({
- error: { message: "Please upload assets before building" },
- });
- return;
- }
- // 保存 theme
- if (theme) {
- db.prepare("UPDATE creatives SET theme = ?, updated_at = datetime('now') WHERE id = ?").run(JSON.stringify(theme), id);
- onThemeSaved?.(id, theme, storageDir);
- }
- const buildId = (0, uuid_1.v4)();
- const themeSnapshot = theme || JSON.parse(creative.theme || "{}");
- db.prepare(`INSERT INTO builds (id, creative_id, platforms, theme_snapshot, status)
- VALUES (?, ?, ?, ?, 'pending')`).run(buildId, id, JSON.stringify(platforms), JSON.stringify(themeSnapshot));
- // 更新创意状态
- db.prepare("UPDATE creatives SET status = 'building', updated_at = datetime('now') WHERE id = ?").run(id);
- // 异步构建(不阻塞响应)
- buildService.enqueue(buildId, id, platforms, themeSnapshot);
- res.status(201).json({
- data: { id: buildId, status: "pending", platforms },
- });
- }
- catch (err) {
- res.status(500).json({ error: { message: err.message } });
- }
- });
- // GET /api/v1/creatives/:id/builds — 构建历史
- router.get("/creatives/:id/builds", (req, res) => {
- const builds = db
- .prepare("SELECT * FROM builds WHERE creative_id = ? ORDER BY created_at DESC LIMIT 20")
- .all(req.params.id);
- res.json({
- data: builds.map((b) => ({
- id: b.id,
- creativeId: b.creative_id,
- status: b.status,
- platforms: JSON.parse(b.platforms),
- previewUrl: b.status === "completed" ? `/q/${b.id}.html` : null,
- results: b.results ? JSON.parse(b.results) : null,
- errorLog: b.error_log,
- startedAt: b.started_at,
- finishedAt: b.finished_at,
- createdAt: b.created_at,
- })),
- });
- });
- // GET /api/v1/builds/:id/status — 构建状态轮询
- router.get("/builds/:id/status", (req, res) => {
- const build = db
- .prepare("SELECT * FROM builds WHERE id = ?")
- .get(req.params.id);
- if (!build) {
- res.status(404).json({ error: { message: "Build not found" } });
- return;
- }
- const previewUrl = build.status === "completed" ? `/q/${build.id}.html` : null;
- res.json({
- data: {
- id: build.id,
- status: build.status,
- previewUrl,
- results: build.results ? JSON.parse(build.results) : null,
- errorLog: build.error_log,
- startedAt: build.started_at,
- finishedAt: build.finished_at,
- createdAt: build.created_at,
- },
- });
- });
- // GET /api/v1/builds/:id/download/all — 下载全部产物 ZIP(必须在 :platform 之前注册)
- router.get("/builds/:id/download/all", (req, res) => {
- const build = db
- .prepare("SELECT * FROM builds WHERE id = ?")
- .get(req.params.id);
- if (!build || build.status !== "completed") {
- res.status(404).json({ error: { message: "Build not found or not completed" } });
- return;
- }
- const zipPath = path_1.default.join(storageDir, "creatives", build.creative_id, "builds", build.id, "all.zip");
- if (!fs_1.default.existsSync(zipPath)) {
- res.status(404).json({ error: { message: "ZIP file not found" } });
- return;
- }
- res.download(zipPath, `playable-ad-${build.id.slice(0, 8)}.zip`);
- });
- // GET /api/v1/builds/:id/download/:platform — 下载单个平台产物
- router.get("/builds/:id/download/:platform", (req, res) => {
- const build = db
- .prepare("SELECT * FROM builds WHERE id = ?")
- .get(req.params.id);
- if (!build || build.status !== "completed") {
- res.status(404).json({ error: { message: "Build not found or not completed" } });
- return;
- }
- const results = JSON.parse(build.results || "[]");
- const result = results.find((r) => r.platform === req.params.platform);
- if (!result) {
- res.status(404).json({ error: { message: "Platform not found in build results" } });
- return;
- }
- const filePath = path_1.default.join(storageDir, "creatives", build.creative_id, "builds", build.id, req.params.platform, "index.html");
- if (!fs_1.default.existsSync(filePath)) {
- res.status(404).json({ error: { message: "File not found on disk" } });
- return;
- }
- res.download(filePath, "index.html");
- });
- return router;
- }
- //# sourceMappingURL=builds.js.map
|