2025-05-09 22:19:35 +01:00

253 lines
7.1 KiB
JavaScript

import dotenv from "dotenv";
import { partModel } from "../../schemas/part.schema.js";
import log4js from "log4js";
import mongoose from "mongoose";
import multer from "multer";
import fs from "fs";
import path from "path";
dotenv.config();
const logger = log4js.getLogger("Parts");
logger.level = process.env.LOG_LEVEL;
// Set storage engine
const partsStorage = multer.diskStorage({
destination: process.env.PART_STORAGE,
filename: async function (req, file, cb) {
// Retrieve custom file name from request body
const customFileName = req.params.id || "default"; // Default to 'default' if not provided
// Create the final filename ensuring it ends with .g
const finalFilename = `${customFileName}.stl`;
// Call callback with the final filename
cb(null, finalFilename);
},
});
// Initialise upload
const partUpload = multer({
storage: partsStorage,
limits: { fileSize: 500000000 }, // 50MB limit
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
}).single("partFile"); // The name attribute of the file input in the HTML form
// Check file type
function checkFileType(file, cb) {
// Allowed ext
const filetypes = /stl|stl|stl/;
// Check ext
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
if (extname) {
console.log(file);
return cb(null, true);
} else {
cb("Error: .stl files only!");
}
}
export const listPartsRouteHandler = async (
req,
res,
page = 1,
limit = 25,
property = "",
filter = {},
) => {
try {
// Calculate the skip value based on the page number and limit
const skip = (page - 1) * limit;
let part;
let aggregateCommand = [];
if (filter != {}) {
// use filtering if present
aggregateCommand.push({ $match: filter });
}
if (property != "") {
aggregateCommand.push({ $group: { _id: `$${property}` } }); // group all same properties
aggregateCommand.push({ $project: { _id: 0, [property]: "$_id" } }); // rename _id to the property name
} else {
aggregateCommand.push({ $project: { image: 0, url: 0 } });
}
aggregateCommand.push({ $skip: skip });
aggregateCommand.push({ $limit: Number(limit) });
console.log(aggregateCommand);
part = await partModel.aggregate(aggregateCommand);
logger.trace(
`List of parts (Page ${page}, Limit ${limit}, Property ${property}):`,
part,
);
res.send(part);
} catch (error) {
logger.error("Error listing parts:", error);
res.status(500).send({ error: error });
}
};
export const getPartRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the part with the given remote address
const part = await partModel.findOne({
_id: id,
});
if (!part) {
logger.warn(`Part not found with supplied id.`);
return res.status(404).send({ error: "Print job not found." });
}
logger.trace(`Part with ID: ${id}:`, part);
res.send(part);
} catch (error) {
logger.error("Error fetching Part:", error);
res.status(500).send({ error: error.message });
}
};
export const editPartRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the part with the given remote address
const part = await partModel.findOne({ _id: id });
if (!part) {
// Error handling
logger.warn(`Part not found with supplied id.`);
return res.status(404).send({ error: "Print job not found." });
}
logger.trace(`Part with ID: ${id}:`, part);
try {
const { createdAt, updatedAt, started_at, status, ...updateData } =
req.body;
const result = await partModel.updateOne(
{ _id: id },
{ $set: updateData },
);
if (result.nModified === 0) {
logger.error("No Part updated.");
res.status(500).send({ error: "No parts updated." });
}
} catch (updateError) {
logger.error("Error updating part:", updateError);
res.status(500).send({ error: updateError.message });
}
res.send("OK");
} catch (fetchError) {
logger.error("Error fetching part:", fetchError);
res.status(500).send({ error: fetchError.message });
}
};
export const newPartRouteHandler = async (req, res) => {
try {
let { ...newPart } = req.body;
newPart = { ...newPart, createdAt: new Date(), updatedAt: new Date() };
const result = await partModel.create(newPart);
if (result.nCreated === 0) {
logger.error("No part created.");
res.status(500).send({ error: "No part created." });
}
res.status(200).send(result);
} catch (updateError) {
logger.error("Error updating part:", updateError);
res.status(500).send({ error: updateError.message });
}
};
export const uploadPartFileContentRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the part with the given id
const part = await partModel.findOne({ _id: id });
if (!part) {
// Error handling
logger.warn(`Part not found with supplied id.`);
return res.status(404).send({ error: "Print job not found." });
}
logger.trace(`Part with ID: ${id}`);
try {
partUpload(req, res, async (err) => {
if (err) {
res.status(500).send({
error: err,
});
} else {
if (req.file == undefined) {
res.send({
message: "No file selected!",
});
} else {
res.send({
status: "OK",
file: `${req.file.filename}`,
});
}
}
});
} catch (updateError) {
logger.error("Error updating part:", updateError);
res.status(500).send({ error: updateError.message });
}
} catch (fetchError) {
logger.error("Error fetching part:", fetchError);
res.status(500).send({ error: fetchError.message });
}
};
export const getPartFileContentRouteHandler = async (req, res) => {
try {
// Get ID from params
const id = new mongoose.Types.ObjectId(req.params.id);
// Fetch the part with the given remote address
const part = await partModel.findOne({
_id: id,
});
if (!part) {
logger.warn(`Part not found with supplied id.`);
return res.status(404).send({ error: "Part not found." });
}
logger.trace(`Returning part file contents with ID: ${id}:`);
const filePath = path.join(process.env.PART_STORAGE, id + ".stl");
// Read the file
fs.readFile(filePath, "utf8", (err, data) => {
if (err) {
if (err.code === "ENOENT") {
// File not found
return res.status(404).send({ error: "File not found!" });
} else {
// Other errors
return res.status(500).send({ error: "Error reading file." });
}
}
// Send the file contents in the response
res.send(data);
});
} catch (error) {
logger.error("Error fetching Part:", error);
res.status(500).send({ error: error.message });
}
};