@lineadraw/sdk
v0.13.0
Published
Script-friendly API over the Linea CAD kernel — open, query, edit, render, and import/export .linea documents headlessly.
Readme
@lineadraw/sdk
A script-friendly API over the Linea CAD kernel: open, create, query, edit,
render, and import/export .linea documents headlessly in Node — no browser,
no server. Built for agents, CLIs, and batch tooling.
import { newDrawing, openDrawing } from "@lineadraw/sdk";
const doc = newDrawing();
const walls = doc.addLayer({ name: "walls", color: "#e8e8e8", lineWidth: 0.5 });
doc.add([
{ type: "polyline", layerId: walls, closed: true,
points: [[0, 0], [6000, 0], [6000, 3000], [0, 3000]] },
{ type: "dimension", points: [[0, 0], [6000, 0]], offset: [0, -500],
styleOverride: { scale: 50 } }, // annotations × drawing scale
]);
doc.createLayout("Plan 1:50", { sheet: "A3", viewport: { scale: "1:50" } });
await doc.exportPng("check.png", { width: 1600 }); // verify by LOOKING at it
await doc.save("plan.linea");
await doc.exportPdf("plan.pdf");Conventions (read once, avoid every common bug)
- Units are millimeters, Y-up. Angles are radians CCW — everywhere in the
object model and in
rotate(). Draw 1:1 (a 6 m wall is 6000 mm); paper scale lives in layout viewports ("1:50"strings viaparseScale). - Never write
.lineaJSON by hand. Every mutation goes through kernel-validated ops (add/update/remove/transforms); invalid input throws with the failing object and field named. - Style by layer: unset
color/lineWidth/lineTypeon objects inherit from the layer. Layer names are unique (addLayerthrows on duplicates) and can be used instead of ids (layer: "walls", query filters). Note:lockedlayers are an editor-UI concept — the SDK does not block edits. - Layer
print: false(plot flag) keeps a layer visible on screen and in SVG/PNG but excludes it from PDF output — construction/guide layers. - Opacity is byLayer too:
opacity(0..1) on a layer is the default for its objects; an object's ownopacityoverrides it. Paints across canvas, SVG, and PDF; DXF/DWG export drops it (no direct mapping). - Annotation scale is per-object: for a 1:N drawing set
scale: Non text,styleOverride: { scale: N }on dimensions, andscale: Non hatches, keepingtextHeightat paper size (2.5 body / 3.5 / 5 titles). - Reads are detached snapshots:
doc.document,doc.objects,getObject,query()return deep clones — mutating them does nothing. - New documents are layout-less;
exportPdfof a layout-less document falls back to one auto-fitted A3 page. transaction(fn)groups edits into one undo step.array(ids, count, delta):countINCLUDES the originals; the returned ids are the copies.- An arc with
startAngle === endAnglerenders as a full circle. - There is no rectangle type — use a closed 4-point polyline.
API surface
newDrawing() / drawingFromJson(text) / openDrawing(path) → Drawing:
- Read:
summary(),objects,layers,layouts,getObject,query({type, layer, color, lineType, content, bbox, inside, near}),bboxOf(ids),length(id),area(id) - Edit:
add(objects, {layout?}),update(ids, patch)orupdate([{id, ...patch}]),remove(ids),transaction(fn),undo(),redo(),setName,setDimStyle,setTextStyle,await setBlockDefinitions(sources),ready() - Layers:
addLayer,updateLayer(nameOrId, patch),removeLayer(nameOrId)(must be empty and not current),setCurrentLayer(nameOrId) - Assets:
addAsset(dataUrl) → assetId(forimageobjects; content-keyed),removeAsset(id)(refused while referenced) - Transform:
move,rotate(radians),scale,mirror,copy,array - Layouts:
createLayout(name, {sheet, orientation, viewport, index}),updateLayoutMeta,removeLayout,parseScale("1:50") - Export:
toSvg/exportSvg,toPng/exportPng,toDxf/exportDxf,toDwg/exportDwg(DWG R2000–2018, default AC1027),toPdf/exportPdf,toJson/save - Import (merge):
importDxf(path)/importDxfText(text)(withunitOverride),importDwg(path)/importDwgData(bytes)(DWG R13–R2018),importPdfData(arrayBuffer)
Full parameter docs are in the bundled dist/index.d.ts JSDoc.
Object types
line (a, b) · polyline (points with optional bulge, closed) · circle ·
arc (CCW start→end) · ellipse (center, majorAxis vector, ratio) ·
hatch (loops — outer + holes, even-odd; fill solid/pattern/lines) ·
text (position, content; default alignment center/center; optional
leaderLines with the arrowhead at index 0) · dimension (linear/angular/
radial/diameter; offset is a vector from points[0] to the dimension line;
linear with >2 points = chain) · block (instances of script definitions) ·
viewport (layouts only) · image (placement of an asset).
Block scripts
document.blockDefinitions is an array of ES-module source strings
(await doc.setBlockDefinitions([...sources]) — async so the script
transpiler is loaded and block geometry is definitive when it resolves).
A block is one defineBlock call:
import { defineBlock } from "lineadraw";
import { polar, add } from "lineadraw/helpers"; // vector-math helpers
export default defineBlock({
id: "chair", // instances reference this
name: "Chair",
params: [{ name: "width", type: "number", default: 450 }],
draw: ({ params }) => [
// Plain object DTOs in block-local coordinates; params.width: number.
{ type: "line", a: { x: 0, y: 0 }, b: { x: params.width, y: 0 } },
],
});Optional members: place — an array of point labels (one pick per label)
or an interactive ({ params, pickPoint, pickObject }) function run once
at insertion (default is one insertion point) — and
paramVisibility({ params }) (hides property rows). params may be the
table literal or a zero-arg function returning it. Imports are limited to
"lineadraw" and "lineadraw/helpers". The instance's first point input
is its pivot: draw sees inputs localized to it, and instance
rotation/scale apply about it. (Plain named exports — incl. the
pre-rename main/defineInput names — remain evaluatable as the frozen
wire form.)
Interchange notes
- DXF/DWG export flattens semantics: block instances are exported as their
evaluated geometry (no
INSERTreuse) andimageobjects are skipped (DXF images reference external files). The export result reports both inskipped. - PDF import extracts vector strokes and text runs (dimensions arrive as exploded geometry). pdf.js loads lazily on first use, as do the PNG rasterizer (native resvg) and the DWG transcoder (bundled WebAssembly).
toSvg({ bbox })culls objects outside the box (they are absent from the file, not merely outside the viewBox).- Opening a document written by a NEWER Linea version throws instead of loading lossily.
- Dimensions validate their point counts per kind (linear ≥ 2, angular ≥ 3, radial/diameter ≥ 2).
Ecosystem
- Linea editor — the browser CAD app; documents
are the same
.lineafiles. @lineadraw/mcp— the same engine as an MCP server, with the full editor as an in-chat app.lineadraw— typings + CLI for authoring block/command marketplace repositories (npm create lineadraw).lineadraw/lineadraw— the public collection: real blocks/commands, agent skill, guides.
