TypeScript client for the Puppet Master HTML-to-PDF server.
Puppet Master server: Codebucket-Solutions/puppet-master
The uploaded server code shows that this client talks to a single POST /pdf endpoint, sends a JSON body shaped like { task: ... }, and downloads the generated PDF as a file stream.
npm install @codebucket/puppet-masterimport { PuppetMaster } from "@codebucket/puppet-master";
const client = new PuppetMaster({
baseUrl: process.env.PUPPET_MASTER_BASE_URL!,
apiKey: process.env.PUPPET_MASTER_API_KEY!,
});
await client.pdf({
pdfPath: "./invoice.pdf",
content: `
<!doctype html>
<html>
<body>
<h1>Invoice</h1>
<p>Hello from Puppet Master.</p>
</body>
</html>
`,
pageOptions: {
waitUntil: "networkidle0",
},
pdfOptions: {
format: "A4",
printBackground: true,
},
});const { PuppetMaster } = require("@codebucket/puppet-master");
const puppetMaster = new PuppetMaster({
baseUrl: process.env.PUPPETMASTER_BASEURL,
apiKey: process.env.PUPPETMASTER_APIKEY,
});
await puppetMaster.pdf({
content: allPages,
launchOptions: {
args: ["--no-sandbox"],
},
pageOptions: { waitUntil: "networkidle0" },
pdfOptions: {
format: "A4",
printBackground: true,
},
pdfPath: "path to your pdf",
});import {
PuppetMaster,
type PuppetMasterClientOptions,
type PdfTaskOptions,
type RemotePdfTaskOptions,
type PageFunctionCall,
} from "@codebucket/puppet-master";interface PuppetMasterClientOptions {
baseUrl: string;
apiKey: string;
}type PageFunctionCall =
| [methodName: string]
| [methodName: string, args: unknown[]];
interface RemotePdfTaskOptions {
launchOptions?: Record<string, unknown>;
pageOptions?: Record<string, unknown>;
pdfOptions?: Record<string, unknown>;
otherPageFunctions?: PageFunctionCall[];
content: string;
}
interface PdfTaskOptions extends RemotePdfTaskOptions {
pdfPath: string;
}Based on the uploaded server code:
POST /pdfreceives{ task }.- The worker launches Puppeteer with
task.launchOptions. - It creates a page and calls
page.setContent(task.content, task.pageOptions). - It generates a PDF with
page.pdf({ ...task.pdfOptions, path }). - It optionally runs
task.otherPageFunctions. - The server downloads the generated file back to the client.
Important caveat:
- In the current server implementation,
otherPageFunctionsruns afterpage.pdf(). That means those calls do not affect the PDF that was already generated.
The client sends this request body to the server:
{
"task": {
"content": "<html>...</html>",
"launchOptions": {},
"pageOptions": {},
"pdfOptions": {},
"otherPageFunctions": [
["waitForNetworkIdle", [{ "idleTime": 500 }]]
]
}
}Notes:
pdfPathis local-only. It is where this client writes the downloaded PDF on the caller's machine.- The client always sends the
x-api-keyheader. - The uploaded server route currently has API-key validation commented out, but the contract still reserves that header.
Use an ordered array of page method calls, not an object.
Examples:
const waitForIdle: PageFunctionCall = ["waitForNetworkIdle", [{ idleTime: 500 }]];
const emulateScreen: PageFunctionCall = ["emulateMediaType", ["screen"]];
const bringToFront: PageFunctionCall = ["bringToFront"];If you are generating code with AI:
- Install
@codebucket/puppet-master. - Import from the package root.
- Create one
PuppetMasterclient withbaseUrlandapiKey. - Call only
await client.pdf(...)because this package currently exposes only one public method. - Provide
contentandpdfPathevery time. - Model
otherPageFunctionsas tuple arrays, not as a map or object. - Do not send
pdfPathin hand-written HTTP requests to the server; that field is client-side only.
import { PuppetMaster, type PageFunctionCall } from "@codebucket/puppet-master";
async function renderPdf(html: string, outputPath: string) {
const otherPageFunctions: PageFunctionCall[] = [
["waitForNetworkIdle", [{ idleTime: 500 }]],
];
const client = new PuppetMaster({
baseUrl: process.env.PUPPET_MASTER_BASE_URL!,
apiKey: process.env.PUPPET_MASTER_API_KEY!,
});
await client.pdf({
content: html,
pdfPath: outputPath,
otherPageFunctions,
});
}For tooling and agent integration, see schemas/pdf-task-options.schema.json.