qr
QR adapter — payload building and styled vector rendering over @leumas/qr. Loaded by the adapter registry (POST /api/adapters/qr/<fn>), and doubles as a chatbot functioncall + MCP tool. Pure and...
qr (adapter system)
QR codes end to end: build the payload string, then render it as a styled vector code with a readability check that says when it will not scan.
Thin over @leumas/qr. The payload builders used to live in this file — ported from leumas-middleware/lib/a.qr, whose server, public/ dashboard, qrcodes.json DB and redirect-app coupling were all stripped. They moved into the package because the generator page, the HTTP export route and this adapter all need them and a browser cannot import an adapter. This file imports the same functions the SPA does, so there is exactly one definition of what a WIFI payload looks like.
Tools (adapters)
| tool | args | result | |
|---|---|---|---|
types | — | { types: [...] } — twelve, from the engine, not a list written here | |
payload | { type, ...fields } | { type, payload } — the string only, no image | |
styles | — | { styles, vocabulary } — the presets, each already checked, plus the closed sets a style may draw from | |
render | { type, ...fields, qrOptions? } | { type, payload, dataUrl, rendered, createdAt } — the unchanged legacy raster lane; dataUrl is a PNG | |
renderStyled | `{ type, ...fields } \ | { text }, style?, size?` | { payload, svg, dataUrl, style, warnings, scannable, matrix } — dataUrl is an SVG URI |
batch | { items, style?, size?, limit? } | { results, rendered, failed, unscannable } |
render is deliberately unchanged. The seeded chatbot functioncall generate_qr calls qr.render with qrOptions and expects a raster data-URL, so its contract is load-bearing. It still goes through qrcode.toDataURL and still draws plain black squares. Everything about module shapes, gradients, styled eyes and logos is in renderStyled.
types and payload now answer for twelve types instead of seven — additive, so no caller breaks.
The two fields worth reading
scannable— false when the style carries an error (too little contrast, an oversized logo).
renderStyled still returns the SVG, because blocking a preview somebody is mid-way through choosing is worse than showing them what is wrong. A save lane must check this.
style— the resolved style, including repairs the engine made (a logo raises error
correction to H). Store this, not the input, or a re-render will not match what was printed.
batch never fails wholesale: a thousand-row import with one malformed phone number returns 999 codes and one named failure. unscannable is counted separately from failed, because those rows did produce an image and a caller printing a sheet needs to know part of it will not read.
No sharp here
PNG and PDF export live in the HTTP route (/api/qr/export), not in this adapter. The registry loads every adapter at boot, so a native libvips binding imported here would be paid by every install including the ones that never render an image — and sharp has to be imported before createApp() to work at all, which is a guarantee a route can make and an adapter cannot.