npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 via parseScale).
  • Never write .linea JSON 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/lineType on objects inherit from the layer. Layer names are unique (addLayer throws on duplicates) and can be used instead of ids (layer: "walls", query filters). Note: locked layers 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 own opacity overrides 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: N on text, styleOverride: { scale: N } on dimensions, and scale: N on hatches, keeping textHeight at 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; exportPdf of a layout-less document falls back to one auto-fitted A3 page.
  • transaction(fn) groups edits into one undo step. array(ids, count, delta): count INCLUDES the originals; the returned ids are the copies.
  • An arc with startAngle === endAngle renders 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) or update([{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 (for image objects; 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) (with unitOverride), 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 INSERT reuse) and image objects are skipped (DXF images reference external files). The export result reports both in skipped.
  • 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 .linea files.
  • @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.