JavaScript (Node.js)
一个 Node.js 脚本,使用 Node 18 及更高版本内置的 fetch 调用 API:无需安装任何包。它列出模板中带标签的变量,用给定的值测量所生成的图纸,并将其导出为 PDF。
下载: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)`);
}
工作原理
- 设置。 密钥来自
PIQ_API_KEY,地址来自PIQ_URL(未设置时为服务本身的地址),还可以选择从PIQ_STORAGE读取存储名称。没有密钥时,脚本会立即停止。 - 模板。
template是每个请求的起始正文:模板的文本作为template,或者在设置了PIQ_STORAGE时,以source给出模板在您存储中的保存位置。values按名称给出L和W。 post将正文以 JSON 形式发送到某个操作,并在X-API-KEY标头中携带密钥。不成功的响应(response.ok为 false)转到fail;其他响应会交回以供读取。fail打印状态,然后打印问题描述:其title、detail,以及errors中的每一项,即字段及其问题。401没有正文,因此先将正文作为文本读取,只有在有正文时才进行解析;不是 JSON 的正文按原样打印。然后脚本以1退出。- Inputs。
POST /inputs只需要模板。其每个inputs都有name、label、kind和value。 - Measure。 使用这些值调用
POST /measure,可得到图纸的width和height,以及在layers中按图层统计的线长;切割长度即Cut图层上的长度。 - Export。
POST /export/pdf返回 PDF 本身而不是 JSON:使用arrayBuffer()读取后写入box.pdf。X-PiQ-Warnings标头表示有多少内容无法按原样导出。 - Save(可选)。 指定了存储时,
POST /save/pdf会导出同一图纸,并将其保存到您存储中的destination,overwrite: true表示替换已存在的文件。响应会说明保存位置及文件大小。
运行
将脚本保存为 box.mjs(.mjs 使其可以在顶层使用 import 和 await),然后:
export PIQ_API_KEY=XXXX-XXXX-XXXX-XXXXX
node box.mjs
它会打印模板中带标签的变量、图纸的尺寸和切割长度,并保存 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)
如果给出模板无法使用的值(例如 "L": "long"),它会打印问题并停止:
Error 400 Bad Request
One or more validation errors occurred.
Some of the values given can't be used.
L: L is a number.
如果密钥不正确,它只会打印 Error 401 Unauthorized:401 没有问题描述。
要试用存储部分,请注册一个存储(请参阅注册存储),将模板以 templates/box.piq
放入其中,并将 PIQ_STORAGE 设置为该存储的名称。这样,模板将从您的存储中读取,
PDF 也会以 drawings/box.pdf 保存到其中,替换已存在的任何文件。