ParaShape Entities — API reference
Two layers: computation values (bare PascalCase namespaces — the function substrate, where math lives) and scene entities (camelCase *Entity namespaces — bound + rendered). Functions are primary; nodes are a curated visual projection of function-calls.
A scene entity is a plain JSON record — NOT a class instance. It has no methods; it is pure data ({ id, geometry, visible?, layer?, material?, label?, sourceKey? }) that the graph passes around, serializes, and watches. There is NO type tag — an entity's KIND is discriminated by the SHAPE of its geometry field (point = [x,y,z]; curve = a NurbsCurveJSON with controlPoints; face = { loops, uvMatrix }). Sniff with the guards isPoint / isCurve / isFace (or entityKind(e)) from schema/graph.ts. This reference documents each kind as that data shape (its fields), plus the free computation functions (Namespace.*, value → value, called in expressions) and the producers / transforms (operations) that produce or process it. Signatures read name(args) → returnType. Operation args are abbreviated — see REFERENCE.md for full args. Tables are generated from src/nodesRegistry/catalog.ts + schema/types.ts.
Data, not an object with methods. The Shape tables are the stored JSON data — there is no
c.length/pointEntity.geometryinstance access. You compute only via free functionsNamespace.fn(value, …)(Curve.length(c),Point.distance(from, to)). Because entities carry no methods, they need no class — they are JSON, the graph is pure functions transforming geometry-as-JSON, and the data stays uniform, serializable, and watchable.
curveEntity · kind = curve geometry · CurveJSON
A 1-D wire or a closed loop (a closed loop is still a Curve), backed by a NURBS curve. No type tag — isCurve(e) is true when e.geometry has controlPoints.
Shape — CurveJSON = { id: string, geometry: NurbsCurveJSON, visible?: boolean, layer?: string, material?: string, label?: string, sourceKey?: string }
| field | type | notes |
|---|---|---|
geometry | NurbsCurveJSON | { degree, knots, controlPoints, weights } (kernel shape); kind is sniffed from this |
id | string | identity |
material? layer? visible? label? | render metadata | |
sourceKey? | string | key of the container child node that produced it (provenance) |
Computation functions — Curve.* (value → value, in expressions)
Curve.length(curve) → numberCurve.closestPoint(curve, point) → pointCurve.pointAt(curve, parameter) → pointCurve.tangentAt(curve, parameter) → vectorCurve.pointAtLength(curve, distance) → pointCurve.startPoint(curve) → pointCurve.endPoint(curve) → pointCurve.divide(curve, count) → point[]
Producers — return: "curveEntity" (add a Curve to the stream)
polyline · spline · rectangle · polygon · arcCenterStartEnd · arcThreePoints · arcTangentEnd · circle · ellipseArc · nurbsCurve · cubicBezier · quadraticBezier · textCurve · (generic:) clone (clone references another node and adds an independent deep copy — new ids; grouping = a container, { key, operations: [...] })
Transforms that target it (derived namespace CurveEntity + generic Instance)
curveSplit · curveFillet · curveChamfer (curve corner rounding/bevel) · curveFill (closed curves → flat faces; nested ring = hole) · curveOffset · curveThicken · curveUnion · curveSubtract · curveIntersect (2D closed-curve boolean — closed curves → closed curve; binary, needs curve) · curveSelfUnion (no-operand reduce n→1 — fuse the own closed curves into one region) · curveReverse · (generic:) move · rotate · resize · mirror · arrayLinear · arrayRadial · arrayCurve · arrayDistances · applyMaterial · applyLayer · visible · name
faceEntity · kind = face geometry · FaceJSON
A flat 3-D polygon: a filled region (holes via extra loops). A solid is Face[] — a box = 6 Faces, no dedicated solid entity. Curved producers tessellate a kernel NURBS surface to Face[] (each triangle a polygon). No type tag — isFace(e) is true when e.geometry has loops.
Shape — FaceJSON = { id: string, geometry: { loops: [x,y,z][][], uvMatrix?: number[16] }, visible?: boolean, layer?: string, material?: string, label?: string, sourceKey?: string }
| field | type | notes |
|---|---|---|
geometry.loops | [x,y,z][][] | 3-D WORLD loops: outer loop first, then holes (a flat polygon) |
geometry.uvMatrix? | number[16] | row-major 4×4 plane→world frame, for UV + 2D projection |
id | string | identity |
material? layer? visible? label? | render metadata | |
sourceKey? | string | key of the container child node that produced it (provenance) |
Kernel boundary — booleans / offset / triangulation run in 2D, so toPolyShape(face) projects the 3-D loops to a 2-D PolyShape (fitting a plane when uvMatrix is absent) and fromPolyShape(shapes, uvMatrix) samples each result loop to polygon vertices and unprojects back to 3-D.
Computation functions — Face.* (value → value, over a face geometry value)
Face.area(face) → numberFace.normal(face) → vectorFace.centroid(face) → pointFace.contains(face, point) → binary
Producers — return: "faceEntity"
extrude · sweep · loft · revolve · patchFromCurve · patchFromCorners · (generic:) clone (loft / revolve / patchFromCurve / patchFromCorners build a kernel NurbsSurface internally, then tessellate → Face[] via nurbsToFaces.)
Transforms that target it (derived namespace FaceEntity + generic Instance)
3-D solid boolean (binary, needs solid): solidUnion · solidSubtract · solidIntersect · solidSelfUnion (no-operand reduce n→1 — fuse all own solids into one) · faceExtrude (face push) · faceOffset (face inset/outset) · edgeFillet (edge rounding) · edgeChamfer (edge bevel) · faceLattice · faceReverse · (generic:) move · rotate · resize · mirror · arrayLinear · arrayRadial · arrayCurve · arrayDistances · applyMaterial · applyLayer · visible · name (solid ops auto-flatten a nested input — a loaded model can be boolean'd directly.)
pointEntity · kind = point geometry · PointJSON
A position marker — the render-only visualization of a coordinate. No type tag — isPoint(e) is true when e.geometry is an array [x,y,z].
Shape — PointJSON = { id: string, geometry: [x,y,z], visible?: boolean, layer?: string, material?: string, label?: string, sourceKey?: string }
| field | type | notes |
|---|---|---|
geometry | [x, y, z] | the position (kind is sniffed from this being an array) |
id | string | identity |
material? layer? visible? label? | render metadata | |
sourceKey? | string | key of the container child node that produced it (provenance) |
Computation functions — Point.*
Point.distance(from, to) → numberPoint.midpoint(from, to) → pointPoint.interpolate(from, to, fraction) → pointPoint.translate(point, offset) → point
Producers — return: "pointEntity"
pointEntity · (generic:) clone
Transforms that target it (generic Instance only)
(generic:) move · rotate · resize · mirror · arrayLinear · arrayRadial · arrayCurve · arrayDistances · applyMaterial · applyLayer · visible · name
Vector · computation value only (no scene entity)
A 3-D direction/magnitude [x, y, z]. A pure value — used by math, never rendered, so it has no *Entity namespace (and like all entities, no type tag).
Computation functions — Vector.*
Vector.length(vector) → numberVector.normalize(vector) → vectorVector.dot(left, right) → numberVector.cross(left, right) → vectorVector.angle(from, to) → numberVector.add(left, right) → vectorVector.subtract(left, right) → vectorVector.scale(vector, factor) → vectorVector.between(from, to) → vector
Registry reference (auto-generated)
Generated from the SSOT registries (
src/schema/types.ts,src/nodesRegistry/catalog.ts,src/schema.ts) byscripts/gen-reference.mjs(pnpm gen:docs). The per-entity narrative above is hand-written; the blocks below mirror the registries exactly. Do not hand-edit between theAUTOGENmarkers — thedocsSynctest fails on drift.
Types
<!-- AUTOGEN:types -->| Type | Kind | Shape | Note |
|---|---|---|---|
curveEntity | sceneEntity | { id: string, geometry: NurbsCurveJSON, visible?: boolean, layer?: string, material?: string, label?: string, sourceKey?: string } | 1D wire — line / arc / bezier / nurbs curve. NO type tag — kind is sniffed from the geometry shape (curve geometry = NurbsCurveJSON, has controlPoints). |
faceEntity | sceneEntity | { id: string, geometry: { loops: [x,y,z][][], uvMatrix?: number[16] }, visible?: boolean, layer?: string, material?: string, label?: string, sourceKey?: string } | Flat bounded region; a solid is faceEntity[]. NO type tag — kind is sniffed from the geometry shape (face geometry has loops). loops = 3D world polygons, outer loop first then holes; uvMatrix = row-major 4×4 plane→world frame for UV / 2D projection. |
pointEntity | sceneEntity | { id: string, geometry: [x,y,z], visible?: boolean, layer?: string, material?: string, label?: string, sourceKey?: string } | Point marker — render-only, from the pointEntity generator. NO type tag — kind is sniffed from the geometry shape (point geometry = [x,y,z]). |
groupEntity | sceneEntity | { id: string, definition: string, transformation: number[16], material?: string, layer?: string, name?: string, visible?: boolean } | ONE placement of a GroupDefinition (SketchUp component model). definition = id of the shared content { id: string, entities: EntityJSON[] } in the model's runtime definitions map — child entities stored ONCE, the definition itself is NOT a scene entity. transformation = column-major 4×4 (translation at indices 12,13,14). A node's value is groupEntity[]: N placements, 1 shared definition. Kind = has definition (no geometry). |
entity | namespace | (curveEntity|faceEntity|pointEntity|groupEntity)[] | Generic ops over any scene entity (move/rotate/array/mirror…). An entity has NO type tag — kind is discriminated by its geometry shape (a groupEntity by its definition field). |
material | namespace | MaterialJSON | Material record — a static materials[] lane entry, referenced by name (applyMaterial). |
layer | namespace | LayerJSON | Layer record — a static layers[] lane entry, referenced by name (applyLayer). |
number | value | number | Unitless number |
length | value | number (mm) | Distance (mm) |
angle | value | number (deg) | Degrees |
binary | value | 0 | 1 | 0 or 1 — multiply with a dimension to collapse it |
string | value | string | Text (single-quoted literal) |
color | value | #rrggbb | #rrggbb hex string |
vector | value | [x,y,z] | Direction [x, y, z] or [x, y] (z defaults to 0) |
point | value | [x,y,z] | Position [x, y, z] or [x, y] (z defaults to 0) |
plane | value | {point:[x,y,z],normal:[nx,ny,nz]} | Infinite plane: a point on the plane + unit normal. Build via Plane.fromPointNormal. |
axis | value | {origin:[x,y,z],direction:[dx,dy,dz]} | Directed half-line: origin + unit direction (magnitude dropped). Build via Axis.fromPointDirection / Axis.fromTwoPoints. |
curve | value | NurbsCurveJSON { degree, knots, controlPoints, weights } | Curve geometry value (NURBS) — the geometry of a curveEntity. Use with Curve.* functions; a curveEntity arg unwraps to this. |
face | value | { loops: [x,y,z][][], uvMatrix?: number[16] } | Face geometry value — the geometry of a faceEntity. Use with Face.* functions; a faceEntity arg unwraps to this. |
surface | value | NurbsSurfaceJSON { degreeU, degreeV, knotsU, knotsV, controlPoints, weights } | NURBS surface value (computation only — not a scene entity). Use with Surface.* functions; a curved generator tessellates one to faceEntity[]. |
function | value | (args) => value | Lambda expression |
model | value | ModelJSON (embedded) | Embedded sub-model. loadModel's input holds the full instanced ModelJSON; its value is the live built sub-model, consumed by placeModel via the loadModel key. |
object | value | object | Parameter group |
group | value | object | Visual group |
area | value | number | Area unit |
volume | value | number | Volume unit |
mass | value | number | Mass unit |
currency | value | number | Currency |
font | value | FontData | Opentype-parsed font object (fetch + parse happens async in Phase 1 via store.loadFonts, fed by the document's static fonts[] lane). Consumed synchronously by the text generator's font arg, which names a fonts[] record. |
fn | value | Function | Callback function: (entity, index) => value. Accepted alongside a static value for per-entity variation. |
Nodes
<!-- AUTOGEN:nodes -->Producers — by return (the entity kind produced; concat into the stream)
curveEntity
curveEntity.polyline— Polyline0: point[] — Ordered vertices [x,y,z] (z optional, defaults 0).1: binary — true closes the loop back to the first point; false leaves it open.
curveEntity.spline— Spline0: point[] — Control points [x,y,z] the smooth curve passes through/near.1: number — Curve smoothness: 1 = polyline, 2 = quadratic, 3 = cubic (most common).
curveEntity.rectangle— Rectangle0: point — One corner of the rectangle.1: point — Opposite corner. The axis with the smallest difference from Point 1 becomes the rectangle's plane (XY/XZ/YZ) — no separate rotate needed to place it on a different plane.
curveEntity.polygon— Polygon0: point — Polygon center [x,y] in the XY plane.1: length — Circumradius — distance from center to each vertex.2: number — Number of edges, minimum 3.
curveEntity.arcCenterStartEnd— Arc (Center)0: point — Arc center [x,y]; the radius = distance from center to start.1: point — Where the arc begins; sets the radius.2: point — Direction the arc sweeps toward (snapped onto the radius).
curveEntity.arcThreePoints— Arc (3 Points)0: point — First endpoint the arc passes through.1: point — Point on the arc between start and end (defines the bulge).2: point — Last endpoint the arc passes through.
curveEntity.arcTangentEnd— Arc (Tangent)0: axis — Start point + leaving tangent direction, as an axis (magnitude irrelevant).1: point — Where the arc ends.
curveEntity.circle— Circle0: point — Circle center [x,y] in the XY plane.1: length — Circle radius.
curveEntity.ellipseArc— Ellipse Arc0: point — Ellipse center [x,y].1: vector — Major-axis vector; its length is the X radius.2: vector — Minor-axis vector (perpendicular to xAxis); its length is the Y radius.3: angle — Sweep in degrees: 360 = full closed ellipse, under 360 = open arc.
curveEntity.cubicBezier— Cubic Bezier0: point — Start point (on curve).1: point — First tangent control point.2: point — Second tangent control point.3: point — End point (on curve).
curveEntity.quadraticBezier— Quadratic Bezier0: point — Start point (on curve).1: point — Tangent control (pulled toward, not on curve).2: point — End point (on curve).
curveEntity.nurbsCurve— NURBS Curve0: point[] — Control points [x,y,z] of the hull; the curve is pulled toward them, not through.1: number — Polynomial degree (clamped to points.length-1): 1 = polyline, 3 = smooth cubic.2: number[] — Knot vector (length = points.length + degree + 1, non-decreasing). Empty = auto clamped-uniform.3: number[] — Per-point weight, > 0 (length = points.length). Empty = uniform 1; higher pulls the curve toward that point.
curveEntity.textCurve— Text0: string — The string to render as outline curves; single-quote the literal.1: font — Font reference; leave '' to use the built-in fallback font.2: length — Cap height of the glyphs in model units.
entity
entity.clone— Clone0: entity[] — Node to copy — returns an independent deep copy with fresh ids.
entity.entities— Entities0: entity[] — Ready-made scene entities as a literal EntityJSON[] (faces/curves/points/groups, UV kept) — emitted verbatim with fresh ids. The static-geometry producer: imports, bakes, AI-authored fixed geometry.
entity.placeModel— Place Model0: model — Model ID to place — emits an independent placement with fresh ids.
faceEntity
faceEntity.extrude— Extrude0: point[] | curveEntity[] | faceEntity[] — Closed loop becomes a solid with caps; open becomes walls. Accepts points, curves, or faces.1: length — Extrusion distance along the profile's normal.2: binary — 1 = closed profiles get top/bottom caps (a solid); 0 = walls only (open shell).
faceEntity.sweep— Sweep0: curveEntity — Path the profile is swept along (open or closed curve).1: curveEntity — Closed cross-section curve carried along the path; yields a solid tube.2: binary — Close the two ends of the swept tube (false = open duct).
faceEntity.loft— Loft0: curveEntity[] — Ordered cross-section curves the skin passes through (2 or more).1: number — Smoothness across sections: 1 = straight (ruled) between curves, 3 = smooth.
faceEntity.revolve— Revolve0: curveEntity[] — Profile curve(s) spun about the axis; a closed profile yields a solid.1: axis — Revolution axis (origin on the axis, direction = spin axis).2: angle — Sweep in degrees: 360 = full solid, under 360 = partial.
faceEntity.patchFromCurve— Patch From Curve0: curveEntity[] — Boundary curves enclosing the region to fill with a smooth surface.
faceEntity.patchFromCorners— Patch From Corners0: point — First corner [x,y,z]; corners wind in order 0→1→2→3.1: point — Second corner [x,y,z].2: point — Third corner [x,y,z], diagonal from corner 0.3: point — Fourth corner [x,y,z].
pointEntity
pointEntity.pointEntity— Render Points0: point[] — Marker positions [x,y,z] to visualize (render-only, not construction geometry).
Transforms — by namespace (the entity kind acted on; process the stream)
CurveEntity
curveOffset— Offset Curve (namespace: CurveEntity, shape: reduce)0: length — Offset amount: positive = outward, negative = inward.
curveThicken— Thicken Curve (namespace: CurveEntity, shape: reduce)0: length — Strip width (the curve is offset half this to each side).1: string — How outer corners are joined: 'round' (arc), 'miter' (sharp point), 'square' (clipped).2: string — How open ends are capped: 'round' (semicircle), 'square' (half-width), 'butt' (flush).
curveUnion— Curve Union (namespace: CurveEntity, shape: reduce)0: curveEntity — The closed curve to merge with this one (2D boolean).
curveSubtract— Curve Subtract (namespace: CurveEntity, shape: reduce)0: curveEntity — The closed curve to cut away from this one (2D boolean).
curveIntersect— Curve Intersect (namespace: CurveEntity, shape: reduce)0: curveEntity — The closed curve to keep only the overlap with (2D boolean).
curveSelfUnion— Curve Self Union (namespace: CurveEntity, shape: reduce)- (no args)
curveFill— Fill (namespace: CurveEntity, shape: map)- (no args)
curveExtrude— Extrude (namespace: CurveEntity, shape: multiply)0: length — Extrusion distance along the profile's normal.1: binary — 1 = closed profiles get top/bottom caps (a solid); 0 = walls only (open shell).
curveReverse— Reverse (namespace: CurveEntity, shape: map)0: binary — true flips direction (curve order / face normal); false leaves it.
curveSplit— Curve Split (namespace: CurveEntity, shape: multiply)0: number — Normalized split position from start (0) to end (1).
curveFillet— Curve Fillet (namespace: CurveEntity, shape: map)0: length — Arc radius rounding each selected corner (curved).1: function — Predicate over a corner vertex and its index selecting which to round; default = all.
curveChamfer— Curve Chamfer (namespace: CurveEntity, shape: map)0: length — Straight setback from each selected corner (flat cut, not an arc).1: function — Predicate over a corner vertex and its index selecting which to cut; default = all.
FaceEntity
solidUnion— Solid Union (namespace: FaceEntity, shape: reduce)0: faceEntity[] — The closed solid (Face[]) to fuse with this one (3D CSG).
solidSubtract— Solid Subtract (namespace: FaceEntity, shape: reduce)0: faceEntity[] — The closed solid (Face[]) to carve out of this one (3D CSG).
solidIntersect— Solid Intersect (namespace: FaceEntity, shape: reduce)0: faceEntity[] — The closed solid (Face[]); keeps only the volume shared by both (3D CSG).
solidSelfUnion— Solid Self Union (namespace: FaceEntity, shape: reduce)- (no args)
faceLattice— Lattice (namespace: FaceEntity, shape: map)0: length — Strut/wall thickness of the lattice shell.1: binary — Close the open border edges of the lattice with caps.
faceExtrude— Face Extrude (namespace: FaceEntity, shape: map)0: length — Distance to push the selected faces along their normal (negative = inward).1: function — Predicate over a face's points and normal selecting which faces to push; default = all.
edgeFillet— Edge Fillet (namespace: FaceEntity, shape: map)0: function — Predicate over an edge's two endpoints selecting which edges to round; default = all.1: length — Rolling-ball arc radius of the rounded edge (curved).2: number — Number of facets across the arc; higher = smoother.
edgeChamfer— Edge Chamfer (namespace: FaceEntity, shape: map)0: function — Predicate over an edge's two endpoints selecting which edges to cut; default = all.1: length — Flat-cut setback from the edge (a straight 45°-style bevel, not an arc).
faceReverse— Reverse (namespace: FaceEntity, shape: map)0: binary — true flips direction (curve order / face normal); false leaves it.
faceOffset— Offset Face (namespace: FaceEntity, shape: map)0: length — Inset (positive) or outset (negative) distance.
Instance
arrayLinear— Linear Array (namespace: Instance, shape: multiply)0: vector — Per-copy step — magnitude IS the spacing (unlike Array Along Distances, where direction is normalized).1: number — Copies to add — the original stays, so 1 duplicates once.
arrayRadial— Radial Array (namespace: Instance, shape: multiply)0: axis — Rotation axis: origin = pivot point, direction = spin axis.1: number — Copies to add around the axis — original + copies spaced evenly over 360°.
arrayCurve— Array Along Curve (namespace: Instance, shape: multiply)0: curveEntity — Path curve the copies are distributed along.1: number — Copies to add along the curve — original at the start, spaced evenly.2: angle — Extra rotation in degrees applied to each copy about the curve tangent.
arrayDistances— Array by Distances (namespace: Instance, shape: multiply)0: vector — Direction to array along — magnitude ignored, see Distances for spacing.1: length[] — Gap after each copy, in order, along Direction. Copy count = number of distances (a partition — no separate Copies arg).
mirror— Mirror (namespace: Instance, shape: multiply)0: plane — Mirror plane (point on plane + normal).1: binary — 1 keeps the original and adds the reflection; 0 flips in place.
move— Move (namespace: Instance, shape: map)0: vector — Displacement to apply.
rotate— Rotate (namespace: Instance, shape: map)0: axis — Rotation axis (origin = pivot point, direction = axis; magnitude irrelevant).1: angle | fn — Rotation angle in degrees (CCW about the axis), or a callback (entity, index) => number, per entity.
resize— Resize (namespace: Instance, shape: map)0: length | fn — Target width along X, or a callback (entity, index) => number, per entity.1: length | fn — Target depth along Y, or a callback (entity, index) => number, per entity.2: length | fn — Target height along Z, or a callback (entity, index) => number, per entity.
applyMaterial— Material (namespace: Instance, shape: map)0: material | fn — A materials[] record name to assign (single-quote literals), or a callback (entity, index) => string, per entity.
applyLayer— Layer (namespace: Instance, shape: map)0: string | fn — Layer name to assign (single-quote literals), or a callback (entity, index) => string, per entity.
visible— Visible (namespace: Instance, shape: map)0: binary | fn — true shows, false hides the entities; or a callback (entity, index) => boolean, per entity.
name— Name (namespace: Instance, shape: map)0: string | fn — Display/export name tag (single-quote literals), or a callback (entity, index) => string, per entity.
Group
groupExplode— Explode (namespace: Group, shape: structural)0: binary — Dissolve this node's nested groups (a placed sub-model / clone) into raw geometry — SketchUp Explode. 1 = recursive; 0 = one level.
looseToGroup— Loose to Groups (namespace: Group, shape: structural)- (no args)
makeGroup— Make Group (namespace: Group, shape: structural)- (no args)
Parameters — value bindings (header lane)
angle
angle.angle— Angle0: angle
boolean
boolean.boolean— Boolean0: binary
color
color.color— Color0: color
length
length.length— Length0: length
loadModel
loadModel.loadModel— Load Model0: model — The embedded instanced ModelJSON (installed by the editor — upload, URL, or catalog pick). Built once and cached; place copies with the placeModel operation.
number
number.number— Number0: number
text
text.text— Text0: string
Model schema (TypeScript)
<!-- AUTOGEN:schema -->type expression = string // any JS expression: arithmetic, parameter key refs, Math.* calls, ternary, arrow functions; literal text single-quoted ('Oak')
type ValueMethod = "angle" | "arrayLength" | "boolean" | "color" | "function" | "length" | "loadModel" | "number" | "text"
type EntityMethod = "applyLayer" | "applyMaterial" | "arcCenterStartEnd" | "arcTangentEnd" | "arcThreePoints" | "arrayCurve" | "arrayDistances" | "arrayLinear" | "arrayRadial" | "circle" | "clone" | "cubicBezier" | "curveChamfer" | "curveExtrude" | "curveFill" | "curveFillet" | "curveIntersect" | "curveOffset" | "curveReverse" | "curveSelfUnion" | "curveSplit" | "curveSubtract" | "curveThicken" | "curveUnion" | "edgeChamfer" | "edgeFillet" | "ellipseArc" | "entities" | "extrude" | "faceExtrude" | "faceLattice" | "faceOffset" | "faceReverse" | "groupExplode" | "loft" | "looseToGroup" | "makeGroup" | "mirror" | "move" | "name" | "nurbsCurve" | "patchFromCorners" | "patchFromCurve" | "placeModel" | "pointEntity" | "polygon" | "polyline" | "quadraticBezier" | "rectangle" | "resize" | "revolve" | "rotate" | "solidIntersect" | "solidSelfUnion" | "solidSubtract" | "solidUnion" | "spline" | "sweep" | "textCurve" | "visible"
type Method = ValueMethod | EntityMethod
type ModelJSON = {
id?: string
title: string
camera?: CameraJSON
materials?: {
name: string
baseColor?: string
texture?: string
tileWidth?: number
tileHeight?: number
colorFactor?: number
opacity?: number
roughness?: number
metallic?: number
}[]
layers?: ({
name: string
color?: unknown[]
lineStyle?: "solid" | "dashed" | "dotted"
})[]
fonts?: {
name: string
url: string
}[]
parameters?: NodeJSON[]
operations?: NodeJSON[]
unit: {
length: "mm" | "cm" | "m" | "in" | "ft" /* default: "mm" */
area?: "mm2" | "cm2" | "m2" | "in2" | "ft2"
volume?: "mm3" | "cm3" | "m3" | "in3" | "ft3" | "L"
mass?: "mg" | "g" | "kg" | "lb" | "oz"
} /* default: {"length":"mm"} */
}
type CameraJSON = {
type?: "perspective" | "orthographic"
position: unknown[]
target: unknown[]
zoom?: number
}
type NodeJSON = OperationJSON | ContainerJSON
type OperationJSON = {
key?: string
label?: expression
enabled?: expression
method: Method
args?: ArgumentJSON[]
animation?: {
keyframes: {
time: number
value: number
}[]
loop?: boolean
}
}
type ContainerJSON = {
key?: string
label?: expression
enabled?: expression
operations: (OperationJSON | ContainerJSON)[]
}
type ArgumentJSON = {
key: string
input: string | Record<string, unknown>
label?: string
min?: expression
max?: expression
step?: expression
options?: OptionJSON[]
}
type OptionJSON = {
label: string
input: expression
}
// JS globals in expression scope — using as node key shadows the global
const JS_RESERVED = ["Math","Number","String","Boolean","Array","Object","isNaN","parseFloat","parseInt"] as const
// ECMAScript reserved words & special identifiers — forbidden as node keys
const JS_KEYWORDS = ["break","case","catch","continue","debugger","default","delete","do","else","finally","for","function","if","in","instanceof","new","return","switch","this","throw","try","typeof","var","void","while","with","class","const","enum","export","extends","import","let","static","super","yield","async","await","implements","interface","package","private","protected","public","of","null","true","false","undefined","NaN","Infinity","arguments","eval"] as constSources of truth: src/nodesRegistry/catalog.ts (producers + transforms; the namespace shown next to a transform is derived catalog/display metadata, not a persisted field — OperationJSON carries no namespace), schema/types.ts (type registry), schema.ts (model contract). The auto-generated blocks above mirror them; the narrative is hand-written.