UNPKG

@fdm-monster/server

Version:

FDM Monster is a bulk OctoPrint, Klipper, PrusaLink and BambuLab manager to set up, configure and monitor 3D printers. Our aim is to provide neat overview over your farm.

186 lines (185 loc) 6.8 kB
import { __exportAll } from "../_virtual/_rolldown/runtime.js"; import { __decorateMetadata } from "../_virtual/_@oxc-project_runtime@0.129.0/helpers/decorateMetadata.js"; import { __decorate } from "../_virtual/_@oxc-project_runtime@0.129.0/helpers/decorate.js"; import { AppConstants } from "../server.constants.js"; import { MulterService } from "../services/core/multer.service.js"; import { FileStorageService } from "../services/file-storage.service.js"; import { FileAnalysisService } from "../services/file-analysis.service.js"; import { slicerApiKeyAuth } from "../middleware/slicer-api-key.middleware.js"; import { GET, POST, before, route } from "awilix-express"; //#region src/controllers/slicer-compat.controller.ts var slicer_compat_controller_exports = /* @__PURE__ */ __exportAll({ SlicerCompatController: () => SlicerCompatController }); var _ref, _ref2, _ref3, _SlicerCompatController; let SlicerCompatController = _SlicerCompatController = class SlicerCompatController { logger; constructor(loggerFactory, fileStorageService, fileAnalysisService, multerService) { this.fileStorageService = fileStorageService; this.fileAnalysisService = fileAnalysisService; this.multerService = multerService; this.logger = loggerFactory(_SlicerCompatController.name); } /** * OctoPrint version endpoint * GET /api/version */ async getVersion(req, res) { res.send({ api: "0.1", server: "1.9.0", text: "OctoPrint 1.9.3" }); } /** * OctoPrint files endpoint - Upload file * POST /api/files/local * * This endpoint mimics OctoPrint's file upload API for slicer compatibility * PrusaSlicer uses: POST /api/files/local with multipart form data */ async uploadFile(req, res) { let files; try { const acceptedExtensions = [...AppConstants.defaultAcceptedGcodeExtensions, ...AppConstants.defaultAcceptedBambuExtensions]; files = await this.multerService.multerLoadFileAsync(req, res, acceptedExtensions, true); if (!files?.length) { res.status(400).send({ error: "No file uploaded" }); return; } const file = files[0]; await this.fileStorageService.validateUniqueFilename(file.originalname); const fileHash = await this.fileStorageService.calculateFileHash(file.path); const fileStorageId = await this.fileStorageService.saveFile(file, fileHash); const filePath = this.fileStorageService.getFilePath(fileStorageId); let metadata = {}; let thumbnails = []; try { const analysisResult = await this.fileAnalysisService.analyzeFile(filePath); metadata = analysisResult.metadata; thumbnails = analysisResult.thumbnails || []; const thumbnailMetadata = thumbnails.length > 0 ? await this.fileStorageService.saveThumbnails(fileStorageId, thumbnails) : []; await this.fileStorageService.saveMetadata(fileStorageId, metadata, fileHash, file.originalname, thumbnailMetadata); } catch (analysisError) { this.logger.error(`Failed to analyze uploaded file: ${analysisError}`); } try { this.multerService.clearUploadedFile(file); } catch (e) { this.logger.error(`Could not remove uploaded file from temporary storage`); } res.status(201).send({ files: { local: { name: file.originalname, origin: "local", refs: { resource: `/api/files/local/${fileStorageId}`, download: `/api/files/local/${fileStorageId}` } } }, done: true, _fdmMonster: { fileStorageId, fileHash, analyzed: Object.keys(metadata).length > 0, thumbnailCount: thumbnails.length, printTime: metadata.gcodePrintTimeSeconds, filament: metadata.filamentUsedGrams } }); this.logger.log(`File uploaded to printer: ${file.originalname} -> ${fileStorageId}`); } catch (error) { if (files?.[0]?.path) try { this.multerService.clearUploadedFile(files[0]); } catch (e) { this.logger.error(`Could not remove uploaded file from temporary storage`); } throw error; } } /** * Files list endpoint * GET /api/files */ async listFiles(req, res) { try { const knownFiles = (await this.fileStorageService.listAllFiles()).map((file) => ({ name: file.metadata?._originalFileName || file.fileName, path: file.fileStorageId, type: "machinecode", typePath: ["machinecode", file.fileFormat], origin: "local", refs: { resource: `/api/files/local/${file.fileStorageId}`, download: `/api/files/local/${file.fileStorageId}` }, gcodeAnalysis: file.metadata ? { estimatedPrintTime: file.metadata.gcodePrintTimeSeconds, filament: { tool0: { length: file.metadata.filamentUsedMm, volume: file.metadata.filamentUsedCm3 } } } : void 0, date: Math.floor(file.createdAt.getTime() / 1e3), size: file.fileSize })); res.send({ files: knownFiles, free: 0, total: 0 }); } catch (error) { this.logger.error(`Failed to list files via printer API: ${error}`); throw error; } } /** * Server endpoint (for compatibility checks) * GET /api/server */ async getServer(req, res) { res.send({ version: "1.9.0", safemode: null }); } }; __decorate([ GET(), route("/version"), __decorateMetadata("design:type", Function), __decorateMetadata("design:paramtypes", [Object, Object]), __decorateMetadata("design:returntype", Promise) ], SlicerCompatController.prototype, "getVersion", null); __decorate([ POST(), route("/files/local"), __decorateMetadata("design:type", Function), __decorateMetadata("design:paramtypes", [Object, Object]), __decorateMetadata("design:returntype", Promise) ], SlicerCompatController.prototype, "uploadFile", null); __decorate([ GET(), route("/files"), __decorateMetadata("design:type", Function), __decorateMetadata("design:paramtypes", [Object, Object]), __decorateMetadata("design:returntype", Promise) ], SlicerCompatController.prototype, "listFiles", null); __decorate([ GET(), route("/server"), __decorateMetadata("design:type", Function), __decorateMetadata("design:paramtypes", [Object, Object]), __decorateMetadata("design:returntype", Promise) ], SlicerCompatController.prototype, "getServer", null); SlicerCompatController = _SlicerCompatController = __decorate([ route("/api"), before([slicerApiKeyAuth()]), __decorateMetadata("design:paramtypes", [ Object, typeof (_ref = typeof FileStorageService !== "undefined" && FileStorageService) === "function" ? _ref : Object, typeof (_ref2 = typeof FileAnalysisService !== "undefined" && FileAnalysisService) === "function" ? _ref2 : Object, typeof (_ref3 = typeof MulterService !== "undefined" && MulterService) === "function" ? _ref3 : Object ]) ], SlicerCompatController); //#endregion export { SlicerCompatController, slicer_compat_controller_exports }; //# sourceMappingURL=slicer-compat.controller.js.map