JavaScript (Node.js)
A Node.js script that uses the API with the fetch built into Node 18 and later: no packages to install. It lists a template's labelled variables, measures the drawing it makes with the values given, and exports it as a PDF.
Download it: box.mjs.
// box.mjs: list a template's inputs, measure it and export it as a PDF with the PiQ SaaS API.
// Node 18 or later; no packages needed.
import { writeFile } from "node:fs/promises";
const key = process.env.PIQ_API_KEY;
const base = (process.env.PIQ_URL ?? "https://saas.parametriq.co.uk").replace(/\/$/, "");
const storage = process.env.PIQ_STORAGE; // optional: a registered storage's name
if (!key) {
console.error("Set PIQ_API_KEY to your API key.");
process.exit(1);
}
const TEMPLATE =
'L=400,"Length"\nW=300,"Width"\nP1=[L,0]\nP2=[L,W]\nP3=[0,W]\nPOLYLINE @1,[P0,P1,P2,P3],TRUE,0';
// the template itself, or (optional) where it is kept in your storage
const template = storage
? { source: { storage, key: "templates/box.piq" } }
: { template: TEMPLATE };
const values = { L: 500, W: 250 };
async function post(path, body) {
const response = await fetch(base + path, {
method: "POST",
headers: { "X-API-KEY": key, "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!response.ok) await fail(response);
return response;
}
async function fail(response) {
console.error(`Error ${response.status} ${response.statusText}`);
const text = await response.text(); // a 401 has no body
if (text) {
let problem = {};
try { problem = JSON.parse(text); } catch { console.error(text); }
if (problem.title) console.error(problem.title);
if (problem.detail) console.error(problem.detail);
for (const [field, messages] of Object.entries(problem.errors ?? {}))
console.error(` ${field}: ${messages.join(" ")}`);
}
process.exit(1);
}
// 1. The template's labelled variables
const { inputs } = await (await post("/inputs", template)).json();
for (const input of inputs)
console.log(`${input.name}: ${input.label} (${input.kind}, ${input.value})`);
// 2. The drawing measured, with the values given
const m = await (await post("/measure", { ...template, values })).json();
const cut = m.layers.find((layer) => layer.layer === "Cut")?.length ?? 0;
console.log(`Size: ${m.width} x ${m.height}, cut length: ${cut}`);
// 3. The drawing as a PDF
const pdf = await post("/export/pdf", { ...template, values });
await writeFile("box.pdf", Buffer.from(await pdf.arrayBuffer()));
console.log(`Saved box.pdf (${pdf.headers.get("X-PiQ-Warnings")} warnings)`);
// 4. Optional: the PDF saved to your storage instead of downloaded
if (storage) {
const destination = { storage, key: "drawings/box.pdf" };
const body = { ...template, values, destination, overwrite: true };
const saved = await (await post("/save/pdf", body)).json();
console.log(`Saved ${saved.key} to ${saved.storage} (${saved.size} bytes)`);
}
How it works
- Settings. The key comes from
PIQ_API_KEY, the address fromPIQ_URL(the service itself if not set) and, optionally, a storage's name fromPIQ_STORAGE. Without a key the script stops at once. - The template.
templateis the body every request starts from: the template's text astemplateor, whenPIQ_STORAGEis set, where it is kept in your storage assource.valuesgivesLandWby name. postsends a body to an operation as JSON, with the key in theX-API-KEYheader. A response that isn't a success (response.okis false) goes tofail; any other is handed back to be read.failprints the status, then the problem description: itstitle, itsdetail, and each entry oferrors, the field and what is wrong with it. A401has no body, so the body is read as text first and only parsed when there is one; a body that isn't JSON is printed as it is. The script then exits with1.- Inputs.
POST /inputsneeds only the template. Each of itsinputshas aname,label,kindandvalue. - Measure.
POST /measurewith the values gives the drawing'swidthandheight, and its lines' lengths by layer inlayers; the cut length is the length on theCutlayer. - Export.
POST /export/pdfanswers with the PDF itself, not JSON: it is read witharrayBuffer()and written tobox.pdf. TheX-PiQ-Warningsheader says how many things couldn't be exported as they are. - Save (optional). With a storage,
POST /save/pdfexports the same drawing and saves it to your storage atdestination,overwrite: truereplacing a file already there. It answers with where it saved it and its size.
Running it
Save the script as box.mjs (the .mjs lets it use import and await at the top level), then:
export PIQ_API_KEY=XXXX-XXXX-XXXX-XXXXX
node box.mjs
It prints the template's labelled variables, the drawing's size and cut length, and saves box.pdf:
L: Length (Number, 400)
W: Width (Number, 300)
D: Depth (Number, 300)
Size: 500 x 250, cut length: 1500
Saved box.pdf (0 warnings)
With a value the template can't use ("L": "long", say), it prints the problem and stops:
Error 400 Bad Request
One or more validation errors occurred.
Some of the values given can't be used.
L: L is a number.
With a key that isn't right it prints only Error 401 Unauthorized: a 401 has no
problem description.
To try the storage part, register a storage (see Register a storage), put a template in
it as templates/box.piq, and set PIQ_STORAGE to the storage's name. The template is then read from your storage,
and the PDF is also saved to it as drawings/box.pdf, replacing any file already there.
See also: API, Inputs, Measure, Export a drawing, Save to your storage, Register a storage, Clients.