Skip to content

Adding a Printer Adapter

PrintStudio’s printer adapters live in packages/integrations/adapters/. Each adapter implements a common PrinterAdapter interface, so the rest of the system doesn’t need to know which protocol a printer uses.

packages/integrations/src/types.ts
interface PrinterAdapter {
// Connection
connect(): Promise<void>;
disconnect(): Promise<void>;
isConnected(): boolean;
// Status
getStatus(): Promise<PrinterStatus>;
getTemperatures(): Promise<Temperatures>;
getPrintProgress(): Promise<PrintProgress>;
// Job control
uploadFile(filename: string, data: Buffer): Promise<void>;
startPrint(filename: string): Promise<void>;
pausePrint(): Promise<void>;
resumePrint(): Promise<void>;
cancelPrint(): Promise<void>;
// Emergency
emergencyStop(): Promise<void>;
}

Create a directory for your adapter:

Terminal window
mkdir -p packages/integrations/src/adapters/my-printer
touch packages/integrations/src/adapters/my-printer/index.ts
touch packages/integrations/src/adapters/my-printer/client.ts
touch packages/integrations/src/adapters/my-printer/types.ts
packages/integrations/src/adapters/my-printer/client.ts
export class MyPrinterClient {
constructor(
private readonly baseUrl: string,
private readonly apiKey?: string
) {}
async getStatus(): Promise<MyPrinterStatus> {
const res = await fetch(`${this.baseUrl}/status`, {
headers: this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {},
});
if (!res.ok) throw new Error(`MyPrinter API error: ${res.status}`);
return res.json() as Promise<MyPrinterStatus>;
}
// ... implement protocol-specific methods
}

index.ts — Adapter that implements PrinterAdapter

Section titled “index.ts — Adapter that implements PrinterAdapter”
packages/integrations/src/adapters/my-printer/index.ts
import type { PrinterAdapter, PrinterStatus, Temperatures } from "../../types.js";
import { MyPrinterClient } from "./client.js";
export class MyPrinterAdapter implements PrinterAdapter {
private client: MyPrinterClient;
private connected = false;
constructor(config: { baseUrl: string; apiKey?: string }) {
this.client = new MyPrinterClient(config.baseUrl, config.apiKey);
}
async connect(): Promise<void> {
const status = await this.client.getStatus();
if (!status.online) throw new Error("Printer not reachable");
this.connected = true;
}
async disconnect(): Promise<void> {
this.connected = false;
}
isConnected(): boolean {
return this.connected;
}
async getStatus(): Promise<PrinterStatus> {
const raw = await this.client.getStatus();
// Map printer-specific status to PrintStudio's unified status
return {
state: raw.printing ? "printing" : raw.idle ? "idle" : "offline",
progress: raw.progress ?? 0,
};
}
async getTemperatures(): Promise<Temperatures> {
// Implement based on your printer's API
throw new Error("Not implemented");
}
// ... implement remaining methods
}
packages/integrations/src/printer-manager.ts
import { MyPrinterAdapter } from "./adapters/my-printer/index.js";
// In the registerPrinter method, add a case:
case "my-printer":
return new MyPrinterAdapter({
baseUrl: config.baseUrl,
apiKey: config.apiKey,
});

Step 3 — Add to IntegrationHub (optional)

Section titled “Step 3 — Add to IntegrationHub (optional)”

If your adapter needs hub-level configuration:

packages/integrations/src/hub.ts
export class IntegrationHub {
myPrinter?: MyPrinterAdapter;
constructor(config: IntegrationHubConfig) {
if (config.myPrinter) {
this.myPrinter = new MyPrinterAdapter(config.myPrinter);
}
}
}
packages/integrations/src/adapters/my-printer/client.test.ts
import { describe, it, expect, mock } from "bun:test";
import { MyPrinterClient } from "./client.js";
describe("MyPrinterClient", () => {
it("returns printer status", async () => {
const client = new MyPrinterClient("http://localhost:1234");
// Mock fetch or use a test server
const status = await client.getStatus();
expect(status).toBeDefined();
});
});

Add your adapter to the package exports in packages/integrations/package.json:

{
"exports": {
"./adapters/my-printer": "./src/adapters/my-printer/index.ts"
}
}

Test your adapter by registering a printer:

Terminal window
curl -X POST http://localhost:8787/api/printers \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"name": "My Printer #1",
"type": "my-printer",
"machineType": "fdm_standard",
"baseUrl": "http://192.168.1.200:1234"
}'
AdapterProtocolComplexity
moonrakerREST (HTTP)Medium — good starting point
octoprintREST (HTTP)Simple
bambuMQTTComplex — async events

The Moonraker adapter is the recommended reference implementation. Start there and adapt the protocol-specific parts.