1// backend/routes/downloadJob.js
2const express = require("express");
3const axios = require("axios");
5const router = express.Router();
7const BUILDER_URL = process.env.BUILDER_URL || "http://127.0.0.1:3001";
10// All /api/* routes already use your JWT middleware globally.
11// We do not need custom authentication here.
13// ------------------------------------------------------------
14// POST /api/download-job
15// ------------------------------------------------------------
16// Create a build job for an installer
17// Requires: tenantId, os
18// Optional: customerId
19// ------------------------------------------------------------
20router.post("/download-job", async (req, res) => {
22 const { tenantId, customerId, os } = req.body;
23 const { randomUUID } = require("crypto");
24 const Redis = require('ioredis');
25 if (!tenantId || !os) {
26 return res.status(400).json({ error: "Missing tenantId or os" });
28 // Generate UUID jobId
29 const jobId = randomUUID();
30 // Enqueue job in Redis
31 const redis = new Redis(require('../config/redis'));
32 await redis.lpush('builder:jobs', JSON.stringify({ jobId, tenantId, customerId, os, created: Date.now() }));
36 statusUrl: `/api/download-job/${jobId}/status`,
37 downloadUrl: `/api/download-job/${jobId}/download`
40 console.error("[Backend] POST /download-job error:", err.message);
41 return res.status(500).json({ error: "Failed to create build job" });
46// ------------------------------------------------------------
47// GET /api/download-job/:jobId/status
48// ------------------------------------------------------------
49// Poll status from builder
50// ------------------------------------------------------------
51router.get("/download-job/:jobId/status", async (req, res) => {
52 const jobId = req.params.jobId;
54 const Redis = require('ioredis');
55 const redis = new Redis(require('../config/redis'));
56 const jobKey = `builder:job:${jobId}`;
57 const jobData = await redis.hgetall(jobKey);
59 if (!jobData || Object.keys(jobData).length === 0) {
60 return res.status(404).json({ error: "Job not found" });
62 // Optionally refresh TTL
64 const { refreshBuilderKeyTTL } = require('../utils/builderKeys');
65 refreshBuilderKeyTTL(jobId).catch(console.error);
67 return res.json(jobData);
69 console.error("[Backend] GET job-status error:", err.message);
70 return res.status(404).json({ error: "Job not found" });
75// ------------------------------------------------------------
76// GET /api/download-job/:jobId/download
77// ------------------------------------------------------------
78// Streams the built installer file from builder through backend
79// ------------------------------------------------------------
80router.get("/download-job/:jobId/download", async (req, res) => {
81 const jobId = req.params.jobId;
84 const builderResponse = await axios({
85 url: `${BUILDER_URL}/download/${jobId}`,
87 responseType: "stream"
91 "Content-Disposition",
92 `attachment; filename=EverydayTechAgent_Installer.exe`
95 builderResponse.data.pipe(res);
97 console.error("[Backend] GET job download error:", err.message);
98 return res.status(404).json({ error: "Installer not found" });
102module.exports = router;