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.

222 lines (221 loc) 8.04 kB
import { ExternalServiceError } from "../../exceptions/runtime.exceptions.js"; import { uploadDoneEvent, uploadFailedEvent, uploadProgressEvent } from "../../constants/event.constants.js"; import { OctoprintRoutes } from "./octoprint-api.routes.js"; import { flattenOctoPrintFiles } from "./utils/file.utils.js"; import { OctoprintHttpClientBuilder } from "./utils/octoprint-http-client.builder.js"; import FormData from "form-data"; //#region src/services/octoprint/octoprint.client.ts /** * OctoPrint REST API * https://docs.octoprint.org/en/master/api/index.html */ var OctoprintClient = class OctoprintClient extends OctoprintRoutes { logger; constructor(loggerFactory, httpClientFactory, eventEmitter2, settingsStore) { super(); this.httpClientFactory = httpClientFactory; this.eventEmitter2 = eventEmitter2; this.settingsStore = settingsStore; this.logger = loggerFactory(OctoprintClient.name); } async getApiVersion(login) { return await this.createClient(login).get(this.apiVersion); } async getServer(login) { return await this.createClient(login).get(this.apiServer); } async login(login) { return await this.createClient(login).post(this.apiLogin, { passive: true }); } async sendConnectionCommand(login, commandData) { await this.createClient(login).post(this.apiConnection, commandData); } async sendPrintHeadJogCommand(login, amounts) { const commandData = { command: "jog", x: amounts.x ?? 0, y: amounts.y ?? 0, z: amounts.z ?? 0 }; return this.sendPrintHeadCommand(login, commandData); } async sendPrintHeadHomeCommand(login, axes) { const commandData = { command: "home", axes: [ ...axes.x ? ["x"] : [], ...axes.y ? ["y"] : [], ...axes.z ? ["z"] : [] ] }; return this.sendPrintHeadCommand(login, commandData); } /** * Ability to jog, home or set feed rate */ async sendPrintHeadCommand(login, commandData) { await this.createClient(login).post(this.apiPrinterHead, commandData); } async sendCustomGCodeCommand(login, commandString) { await this.createClient(login).post(this.apiPrinterCustomCommand, { command: commandString }); } async getJob(login) { return await this.createClient(login).get(this.apiJob); } /** * Ability to start, cancel, restart, or pause a job */ async sendJobCommand(login, commandData) { return await this.createClient(login).post(this.apiJob, commandData); } async sendBedTempCommand(login, targetTemp) { const data = this.getBedTargetCommand(targetTemp); return await this.createClient(login).post(this.apiPrinterBed, data); } async getSettings(login) { return await this.createClient(login).get(this.apiSettingsPart); } async updatePrinterNameSetting(login, printerName) { const settingPatch = this.printerNameSetting(printerName); return await this.createClient(login).post(this.apiSettingsPart, settingPatch); } async getCurrentUser(login) { return await this.createClient(login).get(this.apiCurrentUser); } async getAdminUserOrDefault(login) { return (await this.getCurrentUser(login))?.data?.name; } async getUsers(login) { return await this.createClient(login).get(this.apiUsers); } async getLocalFiles(login, recursive = false, startDir = "") { const url = this.apiGetFiles(recursive, startDir); const response = await this.createClient(login).get(url); if (!response?.data) return []; const data = response.data; const items = data.files || (data.children ? data.children : []); if (!items.length) return []; if (recursive) return flattenOctoPrintFiles(items, startDir); else return items.map((item) => ({ path: item.path || item.name, size: item.size || 0, date: item.date || null, dir: item.type === "folder" })); } async getFile(login, path) { const urlPath = this.apiFile(path); const file = (await this.createClient(login).get(urlPath))?.data; return { path: file.path, size: file.size, date: file.date, dir: file.type === "folder" }; } async downloadFile(login, path) { const urlPath = this.downloadFileLocal(path); return await this.createClient(login).get(urlPath, { responseType: "stream" }); } async getFileChunk(login, filePath, startBytes, endBytes) { const pathUrl = this.downloadFileLocal(filePath); return await this.createClient(login, (o) => o.withHeaders({ Range: `bytes=${startBytes}-${endBytes}` })).get(pathUrl); } async createFolder(login, path, foldername) { const formData = new FormData(); formData.append("path", path); formData.append("foldername", foldername); const headers = { ...formData.getHeaders(), "Content-Length": formData.getLengthSync().toString() }; return await this.createClient(login, (o) => o.withHeaders(headers)).post(this.apiFilesLocal, formData); } async moveFileOrFolder(login, path, destination) { const command = this.moveFileCommand(destination); return await this.createClient(login).post(this.apiFile(path), command); } async postSelectPrintFile(login, path, print) { const command = this.selectCommand(print); const url = this.apiFile(path); await this.createClient(login).post(url, command); } async uploadFileAsMultiPart(login, stream, fileName, contentLength, startPrint, progressToken) { const urlPath = this.apiFilesLocal; const formData = new FormData(); if (startPrint) formData.append("print", "true"); formData.append("file", stream, { filename: fileName, knownLength: contentLength }); const result = await new Promise((resolve, reject) => { return formData.getLength((err, length) => { if (err) reject(/* @__PURE__ */ new Error("Could not retrieve formData length")); resolve(length); }); }); try { const response = await this.createClient(login, (builder) => builder.withMultiPartFormData().withTimeout(this.settingsStore.getTimeoutSettings().apiUploadTimeout).withHeaders({ ...formData.getHeaders(), "Content-Length": result.toString() }).withOnUploadProgress((p) => { if (progressToken) this.eventEmitter2.emit(`${uploadProgressEvent(progressToken)}`, progressToken, p); })).post(urlPath, formData); if (progressToken) this.eventEmitter2.emit(`${uploadDoneEvent(progressToken)}`, progressToken); return response.data; } catch (e) { if (progressToken) this.eventEmitter2.emit(`${uploadFailedEvent(progressToken)}`, progressToken, e?.message); let data; try { data = JSON.parse(e.response?.body); } catch { data = e.response?.body; } throw new ExternalServiceError({ error: e.message, statusCode: e.response?.statusCode, data, success: false, stack: e.stack }, "OctoPrint"); } } async deleteFileOrFolder(login, path) { await this.createClient(login).delete(this.apiFile(path)); } async getPrinterCurrent(login, history, limit, exclude) { const pathUrl = this.apiPrinterCurrent(history, limit, exclude); return await this.createClient(login).get(pathUrl); } async getConnection(login) { return await this.createClient(login).get(this.apiConnection); } async getPrinterProfiles(login) { return await this.createClient(login).get(this.apiPrinterProfiles); } async getSystemInfo(login) { return await this.createClient(login).get(this.apiSystemInfo); } async getSystemCommands(login) { return await this.createClient(login).get(this.apiSystemCommands); } async postServerRestartCommand(login) { await this.createClient(login).post(this.apiServerRestartCommand); } createClient(login, buildFluentOptions) { const baseAddress = login.printerURL; return this.createAnonymousClient(baseAddress, (o) => { if (buildFluentOptions) buildFluentOptions(o); o.withXApiKeyHeader(login.apiKey); }); } createAnonymousClient(baseAddress, buildFluentOptions) { const builder = new OctoprintHttpClientBuilder(); return this.httpClientFactory.createClientWithBaseUrl(builder, baseAddress, (b) => { if (buildFluentOptions) buildFluentOptions(b); }); } }; //#endregion export { OctoprintClient }; //# sourceMappingURL=octoprint.client.js.map