Affinity SDK — C++ Exposure Map
What this document is: A complete map of how the Affinity C++ engine is exposed to JavaScript, derived by analysing every SDK source file. This answers: what can you touch, what is hidden, and what signals clearly indicate a boundary between JS and C++.
How the binding works
The SDK is a three-layer sandwich:
Your JavaScript script
↓
JS wrapper classes (the .js files you require())
↓
Native C++ bindings (affinity:dom, affinity:commands, affinity:common, affinity:story, affinity:ui)
↓
Affinity C++ engine (NOT accessible — no escape hatch)
The native bindings are loaded with require('affinity:xxx') — a special scheme that is not
the file system. These resolve to compiled C++ extension objects baked into the Affinity binary.
You can never call into a C++ binding that the JS SDK doesn't already expose. There is no
ffi, no nativeModule, no way to call arbitrary C++ from JS. If something isn't in the
binding table below, it does not exist for your scripts.
The four native C++ binding modules
| Module | What it provides |
|---|---|
affinity:dom | Document object model — all nodes, spreads, adjustments, filters |
affinity:commands | Command construction — DocumentCommand, CompoundCommandBuilder, etc. |
affinity:common | Shared types — EnumerationResult, ErrorCode |
affinity:story | Text story model — StoryIoFormat |
affinity:ui | Dialog system — all Dialog* APIs, UiApi for alerts/prompts |
affinity:application | App-level — ApplicationApi, ApplicationSettingsApi |
Everything in the JS SDK is a wrapper around calls into one of these six modules.
The architecture signal: *Api classes
Every C++ method is accessed through a class ending in Api. These are the exact boundary
points between JS and C++. The JS wrapper classes receive a native handle from these
Api calls and wrap it in a typed JS object.
// This is what happens inside the SDK — not in your scripts
class ShapeNode extends VectorNode {
get shapeInterface() {
// ShapeNodeApi is C++ — returns a native handle
return new ShapeInterface(ShapeNodeApi.getShapeInterface(this.handle));
// ^^^^^^^^^^^^ C++ boundary
}
}
The handle is an opaque integer pointer into the C++ heap. You never construct handles —
you only receive them from Api calls and pass them back.
What IS exposed to JavaScript
Node types (affinity:dom → nodes.js)
All 29 concrete node classes are accessible:
| Node class | Type guard | Key interfaces |
|---|---|---|
SpreadNode | isSpreadNode | physicalRootInterface, artboards, layers |
DocumentNode | isDocumentNode | pageCount, spreadCount |
GroupNode | isGroupNode | children, visibility |
ContainerNode | isContainerNode | children, fill, line |
ShapeNode | isShapeNode | shapeInterface, fill, line, artboard |
PolyCurveNode | isPolyCurveNode | curvesInterface, artboard |
ImageNode | isImageNode | rasterInterface, imageResourceInterface |
RasterNode | isRasterNode | rasterInterface |
ArtTextNode | isArtTextNode | storyInterface, fill, line |
FrameTextNode | isFrameTextNode | storyInterface, fill, line |
TableTextNode | isTableTextNode | storyInterface (grid-based cells) |
CurvePathTextNode | isCurvePathTextNode | storyInterface |
PolyCurveTextNode | isPolyCurveTextNode | storyInterface |
ShapeTextNode | isShapeTextNode | storyInterface, shapeInterface |
ShapePathTextNode | isShapePathTextNode | storyInterface, shapeInterface |
EmbeddedDocumentNode | isEmbeddedDocumentNode | spreads, artboards, layers |
VectorNode | isVectorNode | fill, line, curves, pictureFrame |
LogicalNode | isLogicalNode | fill, line, transparency |
ColouredLogicalNode | isColouredLogicalNode | layerColour |
PhysicalNode | isPhysicalNode | (base class) |
PatternRasterNode | isPatternRasterNode | rasterInterface (tiled image) |
EnclosureRasterNode | isEnclosureRasterNode | rasterInterface (wrapped raster) |
MeasurementNode | (created via MeasurementNodeDefinition.create(start, end, factor, unitType)) | measurement annotation |
DevelopNode | isDevelopNode | .parameters, .sourceIsRaw, .imageSize (RAW develop) |
Adjustment layer nodes (all exposed)
| Node class | Parameters type |
|---|---|
BlackAndWhiteAdjustmentRasterNode | BlackAndWhiteAdjustmentParameters |
BrightnessContrastAdjustmentRasterNode | BrightnessContrastAdjustmentParameters |
ColourBalanceAdjustmentRasterNode | ColourBalanceAdjustmentParameters |
CurvesAdjustmentRasterNode | CurvesAdjustmentParameters (handle-based) |
ExposureAdjustmentRasterNode | ExposureAdjustmentParameters |
HSLShiftAdjustmentRasterNode | HSLShiftAdjustmentParameters (handle-based) |
InvertAdjustmentRasterNode | (no parameters) |
LevelsAdjustmentRasterNode | LevelsAdjustmentParameters + colourSpace |
NormalsAdjustmentRasterNode | NormalsAdjustmentParameters |
PosteriseAdjustmentRasterNode | PosteriseAdjustmentParameters |
RecolourAdjustmentRasterNode | RecolourAdjustmentParameters |
SelectiveColourAdjustmentRasterNode | SelectiveColourAdjustmentParameters |
ShadowsHighlightsAdjustmentRasterNode | ShadowsHighlightsAdjustmentParameters |
SplitToningAdjustmentRasterNode | SplitToningAdjustmentParameters |
ThresholdAdjustmentRasterNode | ThresholdAdjustmentParameters |
ToneCompressionAdjustmentRasterNode | ToneCompressionAdjustmentParameters |
ToneStretchAdjustmentRasterNode | ToneStretchAdjustmentParameters |
VibranceAdjustmentRasterNode | VibranceAdjustmentParameters |
WhiteBalanceAdjustmentRasterNode | WhiteBalanceAdjustmentParameters |
Filter layer nodes (all exposed)
| Node class |
|---|
AddNoiseFilterRasterNode |
BilateralBlurFilterRasterNode |
BloomFilterRasterNode |
BoxBlurFilterRasterNode |
ClarityFilterRasterNode |
DefringeFilterRasterNode |
DenoiseFilterRasterNode |
DepthOfFieldFilterRasterNode |
DiffuseFilterRasterNode |
DiffuseGlowFilterRasterNode |
DustAndScratchFilterRasterNode |
FieldBlurFilterRasterNode |
GaussianBlurFilterRasterNode |
HighPassFilterRasterNode |
LensBlurFilterRasterNode |
MaximumBlurFilterRasterNode |
MedianBlurFilterRasterNode |
MinimumBlurFilterRasterNode |
MotionBlurFilterRasterNode |
PinchPunchFilterRasterNode |
PixelateFilterRasterNode |
RadialBlurFilterRasterNode |
RippleFilterRasterNode |
ShadowsHighlightsFilterRasterNode |
SphericalFilterRasterNode |
TwirlFilterRasterNode |
UnsharpMaskFilterRasterNode |
VignetteFilterRasterNode |
VoronoiFilterRasterNode |
HalftoneFilterRasterNode |
Node interfaces (exposed as lazy-loaded properties)
Every node exposes some of these interfaces — which ones depend on the node type:
| Interface | Accessed via | Key properties/methods |
|---|---|---|
BaseBoxInterface | node.baseBoxInterface | .baseBox, .constrainingBaseBox |
BlendModeInterface | node.blendModeInterface | .blendMode, .blendOptions, .antialiasingMode |
BrushFillInterface | node.brushFillInterface | .currentDescriptor, .isNoFill |
CompoundOperationInterface | node.compoundOperationInterface | .compoundOperation |
CurvesInterface | node.curvesInterface | .polyCurve |
DescriptionInterface | node.descriptionInterface | .description, .userDescription, .tagColour |
EditabilityInterface | node.editabilityInterface | .isEditable, .isLocalEditable, .isMasterEditable |
ExportableInterface | node.exportableInterface | .exportConfig |
ImageResourceInterface | node.imageResourceInterface | .imageFilePath, .imageFileSize, .fileType |
LayerEffectsInterface | node.layerEffectsInterface | .effects |
LineStyleInterface | node.lineStyleInterface | .lineStyle, .penFillDescriptor, .lineWeight |
PhysicalRootInterface | node.physicalRootInterface | .physicalRootProperties |
PictureFrameInterface | node.pictureFrameInterface | .enabled, .description |
RasterInterface | node.rasterInterface | .width, .height, .format, .pixelSize |
ShapeInterface | node.shapeInterface | .shape, .type, .boundingBox |
StoryInterface | node.storyInterface | .story, .storyRange, .getText() |
TransformInterface | node.transformInterface | .transform, .baseBox |
TransparencyInterface | node.transparencyInterface | .fillDescriptor |
VisibilityInterface | node.visibilityInterface | .globalOpacity, .fillOpacity, .isVisibleInExport |
ArtboardInterface | node.artboardInterface | .isArtboardEnabled, .name, .baseBox, .origin |
TagInterface | node.tagInterface | .tagColour |
MarginsInterface | node.marginsInterface | margins data |
TextFrameInterface | node.textFrameInterface | .ignoreBaselineGrid, .ignoreTextWraps, .isMultiFrameTextFlow |
C++ Api classes from affinity:dom — full method inventory
From nodes.js alone, 142 C++ Api binding classes are imported. Here are the key ones with their exposed method counts:
| Api class | Methods exposed to JS | Notes |
|---|---|---|
NodeApi | 32 | Core tree navigation + box queries |
NodeCastApi | 74 | Type dispatch — one handler per node class |
NodeDefinitionApi | 2 | setTransform, setUserDescription |
EmbeddedDocumentNodeApi | 26 | Placed document properties |
VectorNodeDefinitionApi | 17 | Multi-fill/stroke slot management |
DepthOfFieldFilterParametersApi | 12 | Depth of field parameters |
SpreadNodeApi | 11 | Spread extents, page indices, artboards |
ImageNodeApi | 10 | Image properties, stock info |
CurvesAdjustmentParametersApi | 9 | Curves spline management |
HSLShiftAdjustmentParametersApi | 9 | HSL channel parameters |
FieldBlurFilterParametersApi | 7 | Field blur point management |
TextNodeApi | 6 | Text-specific interfaces |
VectorNodeApi | 7 | Vector-specific interfaces |
LogicalNodeApi | 5 | Fill/line/transparency for logical nodes |
CurvesAdjustmentRasterNodeDefinitionApi | 6 | Curves + colour space |
LevelsAdjustmentRasterNodeDefinitionApi | 6 | Levels + colour space |
Most filter/adjustment Api classes have exactly 4 methods: create, createDefault, getParameters, setParameters.
What is NOT exposed to JavaScript
This is the critical part. The following categories of C++ functionality have no binding visible in the SDK — there is no JS wrapper for them:
1. Pixel-level raster manipulation
/pixelaccessor adds PixelReaderRGBA8, PixelReaderWriterRGBA8, and equivalents for
all 10 colour formats (RGBA8, RGBA16, IA8, IA16, CMYKA8, LABA16, M8, M16, RGBAuf, Mf).
Both read and write pixel access is supported across all formats. Use
node.rasterInterface.createCompatibleBitmap(true) to get a writable bitmap, then
PixelReaderWriterRGBA8.create(bitmap) to read/write pixels, then
DocumentCommand.createReplaceBitmap(sel, bitmap) to push changes back.
2. Master pages / master spreads
The EmbeddedDocumentNode can enumerate spreads including masters via
enumerateSpreads(includeMasters), but there is no MasterSpreadApi or
MasterPageApi. You can detect and navigate to master content but cannot
programmatically create, link, or manage master pages from JS.
3. Styles (character, paragraph, object)
The story system exposes GlyphAttStringType.StyleName for applying named
character styles by name. But there is no StyleSheetApi, ParagraphStyleApi, or
CharacterStyleApi. You can apply a style by name if you already know it, but you
cannot enumerate all styles, create new styles, modify existing styles, or read a node's
applied style name from the C++ side.
4. Tables — partially available
TableTextNode exposes a grid-based text node accessible via /nodes. It has
a storyInterface where cells are separated by HardBreakType.TableCell glyphs. There
is no dedicated TableApi, TableCellApi, or TableRowApi — you navigate cells through
the story text model. Complex table operations (row/column insert/delete, merge, split) are
still not exposed.
5. Find/Replace
No FindReplaceApi. You can implement your own text search by reading storyRanges,
but the application's built-in find/replace engine is not accessible.
6. Symbols / Assets panel
No SymbolApi or AssetApi. Affinity's Symbols feature (reusable components) has no
JS representation.
7. Live paint / pixel persona tools
No PaintBrushApi, LivePaintApi, or InpainterApi beyond the high-level
DocumentCommand.createGenerativeEditImage(). The pixel-level painting tools have
no programmatic API.
8. Constraints / layout rules
No ConstraintApi. The auto-layout and constraint system used in Affinity for responsive
artboards has no JS binding.
9. Linked resources / package management
The SDK has PackageResourcesPolicy in exports but no LinkedResourceApi or
PackageApi for managing linked file relationships or repackaging documents.
10. Colour swatches / palettes
No SwatchApi, PaletteApi, or ColourGroupApi. Document colour palettes and
global swatches are not accessible.
11. Grids and snapping
No GridApi, SnapApi. The grid and snapping system is UI-side only.
12. Print / preflight
No PrintApi or PreflightApi. Printing and PDF preflight checking are not exposed.
13. History beyond undo/redo
DocumentHistory exposes position, size, canUndo, canRedo, and enumeration
of history items. But items are read-only — you cannot inject arbitrary history entries
or branch history. The setPosition setter exists but only navigates linearly.
14. Plugin metadata / custom properties
/taginterface provides TagInterface — a per-node key-value store that persists in the
file. Use node.tagInterface.hasKey(key), .getValueForKey(key), and
DocumentCommand.createSetTagValueForKey(sel, key, value) to read and write arbitrary
string metadata on any node. PredefinedTagKey enumerates Affinity's built-in tag keys.
Boundary signals — how to detect what's missing
When working with the SDK, these patterns indicate you've hit a boundary:
Pattern 1: No *Api class exists
If you want to do something and can't find an *Api class for it in the native module
imports, the feature is not bound. Example: searching for StyleSheetApi — doesn't exist.
Pattern 2: Interface exists but is read-only
Some interfaces expose getters but no corresponding DocumentCommand.createSet* factory.
Example: you can read node.visibilityInterface.fillOpacity but the only way to set it
is through DocumentCommand.createSetVisibility().
Pattern 3: NOT_ALLOWED error code
If a script command returns NOT_ALLOWED, it means the user has restricted AI, filesystem,
or network access in Affinity settings — not that the API doesn't exist.
Pattern 4: Class defined but not exported
Some classes are defined in the SDK source but not in module.exports. Example:
NodeFactory is defined but not exported — it's used internally by createTypedNode().
The complete native method call inventory (nodes.js only)
The following 95 unique C++ method calls are made from nodes.js alone. This is the exact set of C++ operations that the node system relies on:
Navigation
getFirstChild, getLastChild, getNextSibling, getPreviousSibling, getParent,
moveToFirstChild, moveToLastChild, moveToNextSibling, moveToPreviousSibling,
moveToParent, isSameNode
Bounding boxes
getSpreadBaseBox, getExactSpreadBaseBox, getExactSpreadVisibleBox,
getSpreadVisibleBox, getLocalVisibleBox, getLineBox, getTransformedLineBox,
getContentExtentsBox, getContentExtentsBoxOfChildren
Transforms
getBaseToSpreadTransform, getLocalToSpreadTransform, getSpreadToBaseTransform
Interface accessors
getBaseBoxInterface, getBlendModeInterface, getBrushFillInterface,
getCompoundOperationInterface, getCurvesInterface, getDescriptionInterface,
getEditabilityInterface, getExportableInterface, getImageResourceInterface,
getLayerEffectsInterface, getLineStyleInterface, getPhysicalRootInterface,
getPhysicalRootPropertiesInterface, getPictureFrameInterface, getRasterInterface,
getShapeInterface, getStoryInterface, getTransformInterface,
getTransparencyInterface, getVisibilityInterface, getArtboardInterface
Document/spread
getDocument, getPageCount, getSpreadCount, getSpreadExtents,
getFirstPageIndex, getLastPageIndex, isFirstPage, getPageIndexOfPoint,
getPageIndexOfBox, enumerateArtboards, getArtboard, getArtboardCount
Image/raster
getBitmapBrushFillDescriptor, getExtendType, getUpsamplerType,
getStockURL, getStockUserProfileURL, getStockAuthor, getLastRendered, isKOnly,
getExtendEmpty, getLayerColour
Embedded documents
getSelectedSpreadId, getSelectedArtboardId, embeddedDocumentHasSpreads,
embeddedDocumentHasArtboards, embeddedDocumentHasPageBoundingBoxes,
embeddedDocumentHasLayers, getSelectedArtboardOffset, getPageBoundingBoxType,
getPDFPassthrough, canSetPDFPassthrough, getRasterDPI, getOriginalHostDPI,
isAffinityFile, canMakeLinked, canEditEmbeddedImage, getLoadDocumentOptions,
shouldAllowSelectDocument, isArtboardSelected, isArtboardDoc, needsPassword,
enumerateSpreads, enumeratePageBoundingBoxes, enumerateLayerVisibilities
Logical nodes
hasNonMaskChildren, hasNonMaskOrAdjustmentChildren
Physical nodes
canTransformWhileProtectingChildList, canBeExpressedAsVectorClip
Runtime capability detection
There is no SDK_VERSION constant or capability query system. You cannot ask the
SDK at runtime "does this method exist?" — you have to try it and catch errors,
or check the source. The module.exports list in each wrapper file is the authoritative
list of what's available, and app.shortVersion from /application reports the running
Affinity build.
SDK modules
| Module | Native binding | Key capability |
|---|---|---|
/pixelaccessor | affinity:raster | Read+write pixels in all 10 colour formats |
/fonts | affinity:fonts | Enumerate all fonts, families, collections |
/exportconfig | affinity:dom | Per-node export settings (ExportConfig/ExportFormat/ExportScale) |
/glyphs | affinity:story | Typed glyph classes, CharGlyph.create(), glyph enums |
/hatch | affinity:dom | HatchPattern/HatchLine construction |
/rasterbrush | affinity:brushes | Raster brush properties (size, flow, opacity, etc.) |
/buffer | (internal) | Binary buffer manipulation |
/rasterobject | (internal) | Raster object handle wrapper |
/documentproperties | affinity:dom | Document metadata (DPI, size, colour space) |
/drawingscale | affinity:dom | Map/drawing scale (1:100 etc.) |
/taginterface | affinity:dom | Custom key-value tags per node |
/marginsinterface | affinity:dom | Spread margin information |
/pageboxinterface | affinity:dom | Bleed, trim, slug boxes |
/artboardproperties | affinity:dom | Artboard metadata |
/os | affinity:os | OS platform/arch/osName/osVersion/Eol |
/environment | affinity:application | Environment permissions, fileSystemRoots, sdkVersion |
/logging | affinity:common | LogFile file-based logging |
/configuration | affinity:common | ConfigurationItem JSON config parsing |
/pathbrush | affinity:brushes | PathBrush vector brush access |
New native C++ binding modules (affinity:xxx)
| Module | Provides |
|---|---|
affinity:raster | All PixelReader/Writer Api classes for 10 colour formats |
affinity:fonts | FontApi, FontFamilyApi, FontCollectionApi, PanoseApi, font enums |
affinity:brushes | RasterBrushApi, BrushDynamicApi, brush enums |
DocumentCommand factories
Key additions grouped by purpose:
Macro system: createStartRecordingMacro, createStopRecordingMacro, createReplayMacro, createClearMacro, createImportMacro(path), createExportMacro(path)
Raster selections: createRasterSelectAll, createRasterDeselect, createRasterInvertSelection, createRasterReselect, createSetRasterSelectionFromPolygon(polygon, op, antialias, feather) (replaces createRasterSelectPolygon), createSetRasterSelectionFromObject(sel, op, antialias, feather), createGrowShrinkRasterSelection(radius, circular), createFeatherRasterSelection(radius), createSmoothRasterSelection(radius), createOutlineRasterSelection(radius, alignment, circular), RasterSelectionOutlineAlignment enum
Opacity control: createSetOpacity(sel, opacity), createSetBrushFillOpacity(sel, opacity, opts), createSetLineFillOpacity(sel, opacity, opts)
Fill anchoring: createSetBrushFillIsAnchoredToSpread, createSetPenFillIsAnchoredToSpread, createSetTransparencyFillIsAnchoredToSpread
Tag metadata: createSetTagValueForKey(sel, key, value), createSetTagValueForPredefinedKey(sel, predefinedKey, value)
Blend options: createSetBlendGamma(sel, gamma), createSetBlendRanges(sel, blendOptions), createSetAntialiasingMode(sel, mode)
Snapshots: createAddDocumentSnapshot, createDeleteDocumentSnapshot, createRestoreDocumentSnapshot, createSetCurrentSnapshot, createSetCurrentSnapshotFromHistoryItem
Document: createSetDocumentProperties, createConvertDocumentFormat(format), createGroupTransform, createSetWindingMode, createSetExportConfig, createMoveNodes, createFlatten, createMergeVisible, createSetSelection(sel)
Spread: createSetSpreadSizeWithAnchor, createSetSpreadDocumentProperties
History: createSetHistoryIndex(index), createCycleAlternateFutures(index)
Text frame: createSetTextFrameIgnoreBaselineGrid(sel, ignore), createSetTextFrameIgnoreTextWraps(sel, ignore)
Layer effects — outline fill: createSetOutlineLayerEffectFill(sel, fill, index, enableIfDisabled), createSetOutlineLayerEffectFillTransform(sel, transform, index, enableIfDisabled), createSetOutlineLayerEffectFillType(sel, type, index, enableIfDisabled), createSetGradientOverlayLayerEffectFill(sel, fill, index, enableIfDisabled), createSetGradientOverlayLayerEffectFillTransform(sel, transform, index, enableIfDisabled)
AI: createRemoveBackground(sel), createSelectSubject(sel)
Artboard: createAddArtboard(spread, bounds)
Curve editing: createAddCurve(sel), createAddCurveNode(sel, point, type), createSmoothCurves(sel), createDeleteCurveNodes(sel), createScissorCut(sel), createKnifeCut(sel)
Document: createSetDocumentUnits(sel, units), createSetPageDocumentProperties(sel, props)
Guides: createAddHorizontalGuide(pos), createAddVerticalGuide(pos), createMoveHorizontalGuide(sel, pos), createMoveVerticalGuide(sel, pos), createRemoveHorizontalGuide(sel), createRemoveVerticalGuide(sel)
Embedded documents: createSetEmbeddedDocumentAllLayersVisibility(sel, visible), createSetEmbeddedDocumentLayerVisibility(sel, layerIndex, visible), createSetEmbeddedDocumentPDFPassthrough(sel, passthrough), createSetEmbeddedDocumentPageBoundingBoxType(sel, type), createSetEmbeddedDocumentSelectedArtboardID(sel, id), createSetEmbeddedDocumentSelectedSpreadID(sel, id)
Layer effects: createSetAllLayerEffectsScaleWithObject(sel, scale), createSetOuterShadowLayerEffectKnocksOut(sel, knocksOut, index, enableIfDisabled), createSetBevelEmbossLayerEffectAzimuth(sel, azimuth, enableIfDisabled), createSetBevelEmbossLayerEffectElevation(sel, elevation, enableIfDisabled)
Raster selection: createRasterFloodSelect(x, y, tolerance, antialias, feather) (magic wand), createRasterSelectPolygon(polygon, operation, antialias, feather) (available alongside createSetRasterSelectionFromPolygon)
Other: createHideSelection, createSplitCurve, createInsertGlyph
Additional factories
Boolean operations: createBoolOpUnion(sel), createBoolOpSubtract(sel), createBoolOpIntersect(sel), createBoolOpXor(sel), createDivideShapes(sel)
Text frame threading: createLinkTextFrame(srcNode, destNode), createUnlinkTextFrame(node)
Merge: createMergeDown(), createMergeSelected()
Picture frame: createPopulatePictureFrame(contentNode, selection)
Raster auto-fixes: createRasterAutoLevels(sel), createRasterAutoContrast(sel), createRasterAutoColours(sel), createRasterAutoWhiteBalance(sel)
Raster fill: createRasterFill(sel, mode, colour, opacity, blendMode), createRasterFloodFill(sel, point, tolerance, isContiguous, antialias, samplingSource, blendMode, colour)
RAW Develop: createSetDevelopParameters(sel, developParameters)
Measurement: createSetMeasurementUnits(unitType), createSetMeasurementPrecision(useDocumentPrecision, decimalPlaces), createSetMeasurementAnnotationOffset(node, offset), createSetMeasurementShowEndpointMarkers(show)
Enum member reference
Values below marked ★ were read at runtime (Object.entries dump in Affinity 3.3); the rest are member names from the official docs at https://sdk.affinity.studio/ (which publishes no values — never infer values from documentation order).
Runtime-verified (name = value) ★:
| Enum | Members |
|---|---|
GradientFillType ★ | Linear=0, Elliptical=1, Radial=2, Conical=3 |
RasterSelectionLogicalOperation ★ | New=0, Add=1, Subtract=2, Intersect=3 (no Replace — use New) |
NodeMoveType ★ | Before=0, After=1, Inside=2 |
NodeChildType ★ | Main=0, Enclosure=1, MasterSpread=2, WrapShape=3, StoryPin=4 |
ShapeCornerType ★ | Round=0, Straight=1, RoundInverse=2, Cutout=3, None=4 |
ContentType ★ | Main=0, Frame=1, Cell=2 |
VisibilityMode ★ | Main=0, Export=1 |
ShapeArrowEndStyle ★ | None=0, Arrow=1, TailTriangular=2, TailSquare=3, Circle=4, HalfCircleInner=5, HalfCircleOuter=6, Diamond=7, Box=8, Barb=9, Chevron=10 (no Triangle — use Arrow) |
QRPayloadType ★ | Text=0, URL=1, Phone=2, SMS=3, Email=4, WhatsApp=5, FaceTime=6, Location=7, Wifi=8, VEvent=9, VCard=10, DataMerge=11 |
FillType ★ | Unknown=0, None=1, Solid=2, Gradient=3, Bitmap=4, Mesh=5, Hatch=6, Diffusion=7 |
Member names from official docs (values not published):
| Enum | Members |
|---|---|
SubSelectionType | CurveEdge, CurveNode, Text, Table, ExportFormat, Fill, LineFill, Transparency, FillMesh, LineFillMesh, TransparencyMesh, GeometryModifier, FillDiffusion |
DialogItemType | Unknown, Separator, Switch, ComboBox, ButtonSet, RadioGroup, StaticText, UnitValueEditor, CheckBox, SpatialAnchor, ColourPicker, TextBox, FontPicker, FillEditor, StrokeEditor, Group, Column, ColumnStack, Button |
SpatialAnchor | None, TopLeft, CentreLeft, BottomLeft, TopCentre, Centre, BottomCentre, TopRight, CentreRight, BottomRight, FocalPoint |
PackageResourcesPolicy | None, IncludeImages, IncludeTexts, IncludeCSS, IncludeUnrestrictedFonts, IncludeRestrictedFonts |
PageBoundingBoxType | MediaBox, CropBox, TrimBox, ArtBox, BleedBox, MinimumContent, MinimumVisibleContent, MaximumContent, MaximumVisibleContent |
RasterFillMode | Colour, Foreground, Background, Inpainting, History |
SamplingSource | CurrentLayer, AllLayers |
RasterFloodFillSamplingSource | CurrentLayer, CurrentLayerAndBelow, LayersBeneath |
RasterSelectionOutlineAlignment | Outside, Centre, Inside |
CurveNodeStyle | None, Cusp, Smooth, Smart |
CurveNodeType | OnCurve, Cubic1, Cubic2 |
CurveCornerType | None, Round, Inverse, Straight, CutOut |
LayerEffectType | BevelEmboss, Outline, PhongBevel, InnerShadow, InnerGlow, ColourOverlay, GradientOverlay, OuterGlow, OuterShadow, GaussianBlur |
DevelopToneCurveMethod | Standard, Compressed, Natural, HighContrast, Log |
DevelopInvertMethod | InfraredRB, InfraredRGB, Negative |
DevelopDetailRefinementMethod | UnsharpMask, HighPass, MultiBand |
RasterExtendType | Zero, Repeat, Wrap, Mirror |
RasterResamplerType | Default, BilinearMipmap, NearestNeighbourMipmap, NearestNeighbour, Bilinear, Bicubic, SeparableLanczos3, NonseparableLanczos3, AntialiasedNearestNeighbourMipmap, Mitchell |
ConstraintType | NotSizable, FixedMinX, ScaleWidth, FixedMaxX, FixedMinY, ScaleHeight, FixedMaxY, FixedAspectMin, FixedAspectMax, ForceAspectMin, ForceAspectMax, StretchToFit, NoScale, Default |
FontField | PostscriptName, FamilyName, Weight, IsItalic, Width, Panose, VarParams, RibbiFamily, WwsFamily |
CopyOptions | None, SkipExisting, OverwriteExisting, UpdateExisting, Recursive, CopySymlinks, SkipSymlinks, DirectoriesOnly, CreateSymlinks, CreateHardLinks |
FileOrigin | Begin, Current, End |
PathType | None, NotFound, File, Directory, Symlink, Block, Character, Fifo, Socket, Unknown |
PermOptions | Replace, Add, Remove, NoFollow |
UnitCategory | Distance, Angle, Relative, Data, Temperature |
ShapeBoolParam | Arrow_LeftIsProportional, Arrow_RightIsProportional, CalloutEllipse_AbsoluteSizes, CalloutRectangle_SingleRadius, CalloutRectangle_AbsoluteSizes, Polygon_SmoothPoints, Rectangle_SingleRadius, Tear_FixedBallSize |
ShapeEnumParam | Rectangle_BottomLeftCornerType, Rectangle_BottomRightCornerType, Rectangle_TopLeftCornerType, Rectangle_TopRightCornerType, Arrow_LeftEndStyle, Arrow_RightEndStyle |
ShapeFloatParam | Arrow_LeftLength, Arrow_LeftInnerOffset, Arrow_RightLength, Arrow_RightInnerOffset, Arrow_Thickness, CalloutEllipse_TailAngle, CalloutEllipse_TailEndPosition, CalloutEllipse_TailHeight, CalloutRectangle_BottomLeftRadius, CalloutRectangle_BottomRightRadius, CalloutRectangle_TopLeftRadius, CalloutRectangle_TopRightRadius, CalloutRectangle_TailEndPosition, CalloutRectangle_TailHeight, CalloutRectangle_TailPosition, CalloutRectangle_TailWidth, Cloud_InnerRadius, Cog_Curve, Cog_HoleRadius, Cog_InnerRadius, Cog_NotchSize, Cog_ToothSize, Crescent_ArcLeft, Crescent_ArcRight, Diamond_Position, DoubleStar_InnerRadius, DoubleStar_PointRadius, Heart_Spread, Pie_InnerRadius, Pie_StartAngle, Pie_EndAngle, Pie_Sweep, Polygon_Curve, Rectangle_BottomLeftRadius, Rectangle_BottomRightRadius, Rectangle_TopLeftRadius, Rectangle_TopRightRadius, Segment_Angle, Segment_LowerLine, Segment_UpperLine, SquareStar_Cutout, Star_CircleOuterRadius, Star_CircleInnerRadius, Star_InnerRadius, Star_LeftCurve, Star_RightCurve, Trapezoid_LeftPosition, Trapezoid_RightPosition, Triangle_Position, Tear_BallSize, Tear_Curve, Tear_Bend, Tear_TailPosition |
ShapeIntParam | Cloud_BubbleCount, Cog_ToothCount, DoubleStar_PointCount, Polygon_SideCount, SquareStar_SideCount, Star_PointCount |
Enum behavior (per the September 2026 release notes): SDK enums expose parse(name, throwIfMissing) — returns null for an unknown name unless throwIfMissing is true. Enum values compare directly without extracting .value, and value is now an instance property.
| TonalRangeType | Shadows, Midtones, Highlights |
| ToneCompressionMethod | Basic, Natural, Bright, Contrast, Filmic, Punchy, PBRNeutral, Log |
| ToneStretchMethod | Basic, Arcsinh, Logarithmic, Structural, ColourPreserving |
| DevelopDetailRefinementMethod / DevelopToneCurveMethod / DevelopInvertMethod | UnsharpMask, HighPass, MultiBand / Standard, Compressed, Natural, HighContrast, Log / InfraredRB, InfraredRGB, Negative |
| DocumentLoadMode | Application, Spreads, Artboards |
| HalftoneDotType / HalftoneScreenType | Cosine, Round, Line / Mono, Colour, Line, Circular |
| AntialiasingMode | Inherit, ForceOn, ForceOff |
| CompoundOperation | Union, Intersect, Subtract, Xor |
| ExportScalePreset | Standard, Mult2x, Mult3x, Width100, Height50, Square64, Square64Mult2x, Width32Height32 |
| ExportScaleSizeType | None, Width, Height, Square, WidthHeight |
| FileType | JPEG, PNG, TIFF, WEBP, HDPhoto, RAW, GIF, JPEG2000, BMP, TGA, OpenEXR, HDR, Unknown, Affinity, HEIF, FITS, Plugin |
| ShapeMajorAxis / ShapeSpiralStyle / Shape*Param / ShapeCornerIndex | See /shapes module; corner indices TopLeft/TopRight/BottomLeft/BottomRight |
| CapsType, SuperSubType, LeadingOverrideType, OpticalAlignmentType, TocRoleType, TypographicLineType | Glyph typography enums (see /glyphatts) |
| ParagraphAlignXType, ParagraphLeadingType, ParagraphStartAtHardBreakType, ParagraphUseSpaceBeforeMode, ParagraphPDFExportTagType, ParagraphLineBreakModeType | Paragraph behaviour enums (see /paragraphatts) |
| StoryIoFormat, TextDefaultType (Art, Frame, Unknown, Measurement), WordPartType | Story/text enums |
| TableEdgeSelector (None … All, 14) / TableAxis | Table enums |
| WifiEncryptionType, DocumentFieldType, FieldDataType, FillerTextType, NoteType, NotePosition | Field/QR enums |
| UnitCategory, UserUnitType, UnitType | Units enums |
| AddNoiseType (Gaussian, Uniform), BloomMethod (Contrast, Bright), DepthOfFieldMode (Elliptical, TiltShift), SelectiveColour (9 channels), ShadowsHighlightsVersion (Default, V16) | Filter/adjustment enums |
| LineCommandDefaultsMode, StrokeFillType, WindingOrder, BevelEmbossType, ImagePlacement, ColourSpaceType, RasterIntent | Named in module indexes; members per official docs |
Documented officially but NOT script-reachable in 3.3 (present in the web API index, absent from JSLib — native layer only, do not use from scripts; re-verified against the 3.3 JSLib): QRPayloadDataMerge (QR payload kind 11 exists in the QRPayloadType enum but has no JSLib wrapper; VEvent (9) likewise), ImportOptions (CAD import options), DocumentView (empty handle).
Geometry classes (from /geometry)
| Class | Key factories/methods |
|---|---|
Polygon | create(), createLine(), createTriangle(p1,p2,p3), createDiamond(rect), createLozenge(p1,p2,radius), createRectangle(rect) |
Curve | create(), createLine(), createRectangle(), createEllipse(), createDiamond(), createLozenge(), createPrecisionUnitCircle() |
CubicBezier | .evaluate(t), .split(t), .getTangent(t), .getNormal(t), .getCurvature(t), .getClosestPoint(pt), .length, .getParamAtLength(len), .clone(), .reversed(), .transformed(xf) |
CurveBuilder | create(), .begin(), .lineTo(), .close(), .addBezier(), .addArc(), .addEllipse(), .versineTo(), .bulgeTo(), .createCurve() |
Selections (from /selections)
| Class | Key factories/methods |
|---|---|
TableSubSelection | fromSubSelection(sub) — .anchor, .caret, .isRectangle, .cells, .enumerateCells(), .enumerateEdges() |
TextSelection | create(ranges) — .ranges, .caret, .anchor, .isEmpty |
FillSubSelection | fromSubSelection(sub) — .index |
LineFillSubSelection | fromSubSelection(sub) — .index |
Story attribute runs
| Iterator | Yields |
|---|---|
story.glyphAttRuns | {glyphAtts, begin, end} |
story.paragraphAttRuns | {paragraphAtts, begin, end} |
story.attRuns | {glyphAtts, paragraphAtts, begin, end} |
Dialog controls (from /dialog)
| Class | Key properties/methods |
|---|---|
Dialog | create(title), .addColumn(), .runModal(), .findControl(id), .isRunningModal, .setItemsVisibility(showIDs, hideIDs) |
DialogFontPicker | .font (Font), .fontFamily (FontFamily), .fontCollection (FontCollection), .isFullWidth |
DialogFillEditor | .fill, .isStrokeFill |
DialogStrokeEditor | .stroke (LineStyleDescriptor) |
DialogSpatialAnchor | .value (SpatialAnchor enum) |
DialogButton | .alignment, .onClickHandler, .isFullWidth |
DialogUnitValueEditor | .value, .units, .noMinValue, .noMaxValue, .precision |
DialogColourPicker | .value (Colour), .allowPickNone, .allowNoise |
createSetEditable — argument order
// Selection is first argument, editable flag is second
DocumentCommand.createSetEditable(selection, true) // unlock
DocumentCommand.createSetEditable(selection, false) // lock
Layer effect families
The following effect families are available in addition to OuterShadow, Outline, InnerGlow, and GaussianBlur:
| Effect | Key commands |
|---|---|
| OuterGlow | createSetOuterGlowLayerEffect* — colour, radius, opacity, intensity, blend mode |
| InnerShadow | createSetInnerShadowLayerEffect* — colour, offsetAngle, radius, opacity, intensity (indexed) |
| ColourOverlay | createSetColourOverlayLayerEffect* — colour, opacity, blend mode (indexed) |
| GradientOverlay | createSetGradientOverlayLayerEffect* — fill, fillTransform, blend mode (indexed) |
| BevelEmboss | createSetBevelEmbossLayerEffect* — radius, depth, direction, soften, type, shadow/highlight colours |
| PhongBevel | createSetPhongBevelLayerEffect* — ambient, diffuse, specular, shininess, createSetPhongBevelLayerEffectLights(count) |
All layer effects must be executed individually — CompoundCommandBuilder is a silent no-op for effect commands.
Fill types
| Class | Factory | Description |
|---|---|---|
HatchFill | HatchFill.create(pattern, units, penColour, brushColour, lineWeight) | Repeating line pattern |
BitmapFill | BitmapFill.create(bitmap, extendType, resamplerType, ignoreAlpha) | Tiled raster image |
GradientFill | GradientFill.create(gradient, gradientType) | Linear/radial/conical gradient |
MeshFill | MeshFill.create(mesh) + ColourMesh.createFromColour(colour, nodes) | Mesh gradient grid (ColourMesh with setNodePosition/setNodeColour) |
DiffusionFill | DiffusionFill.create(curveSet) + DiffusionCurveSet.create() | Diffusion curve fill (DiffusionCurveKind: Bezier/Ellipse/Arc/Line) |
FillDescriptor.createSolid() accepts a Colour directly, as do createSetBrushFill / createSetPenFill. The FillType enum includes Mesh and Diffusion.
Document convenience methods
Document exposes direct convenience methods for most common operations, eliminating the need to call DocumentCommand.create* explicitly. These include: doc.undo(), doc.redo(), doc.selectAll(), doc.deleteSelection(), doc.showSelection(), doc.hideSelection(), doc.lockSelection(), doc.unlockSelection(), doc.setOpacity(), doc.setBrushFillOpacity(), doc.setLineFillOpacity(), doc.setBrushFillDescriptor(), doc.setPenFillDescriptor(), doc.setLineWeight(), doc.setLineWeightPts(), doc.setLineCap(), doc.setLineJoin(), doc.convertToCurves(), doc.rasteriseObjects(), doc.flatten(), doc.mergeVisible(), doc.addGuide(), doc.moveGuide(), doc.removeGuide(), doc.addRectangularArtboard(), doc.imageTrace().
AI convenience methods: doc.generateImage(prompt), doc.detectDepth(), doc.colourise(), doc.generativeEditImage(prompt), doc.removeBackground(), doc.selectSubject().
Document classes
| Class | Purpose |
|---|---|
DocumentHistory | Access undo history — position, size, canUndo, canRedo, getItem(index), items |
DocumentHistoryItem | Individual history entry — description, thumbnail, command |
NewDocumentOptions | Full control over new document creation — dimensions, DPI, margins, colour profile |
DocumentPreset | Enumerate built-in presets via DocumentPreset.all |
LoadDocumentOptions | Control DPI, password, colour space when loading |
FileExportArea | createForSpreads(str), createForSelection(sel) in addition to existing factory methods |
Summary counts
| Category | Count |
|---|---|
| Native C++ binding modules | 9 |
| C++ Api classes in nodes.js | 142 |
| JS wrapper modules | ~75 |
| DocumentCommand factories | ~351 |
| Node types accessible | 31 concrete + ~10 base |
| Adjustment layer types | 19 |
| Filter layer types | 30 (+ HalftoneFilterRasterNode) |
| Node interfaces | 21+ |
| Major feature categories exposed | pixel access, custom tags, tables, fills, AI, develop |
| Major features still NOT exposed | several categories |
Release 3.3 — analysed from live Affinity SDK via MCP.
Official SDK example scripts
The SDK ships 34 official example scripts that are instructive as canonical patterns from the Affinity team. They are mirrored 1:1 in phase-5-official-examples/ — see its [README(./phase-5-official-examples/README.md) for the full table:
| File | What it demonstrates |
|---|---|
examples/boldItalics.js | StoryDelta.createWeight(), StoryDelta.createItalic(), StoryDelta.createComposite() |
examples/addGuides.js | DocumentCommand.createAddGuide(), unionRects(), UnitType.Pixel/Millimetre |
examples/setDocumentFormat.js | doc.format = RasterFormat.xxx, dialog combo pattern |
examples/addPoints.js | Curve node manipulation |
examples/alignToPage.js | Alignment via transform |
examples/adjustPageItems.js | Batch node adjustment |
Additional confirmed APIs
StoryDelta factory methods:
StoryDelta.createWeight(FontWeight.Bold)— applies font weightStoryDelta.createItalic(bool)— applies italicStoryDelta.createComposite([delta1, delta2])— combines multiple deltas
Geometry utility:
unionRects(rect1, rect2)from/geometry— combines two Rectangle bounding boxes
LoadDocumentOptions (exported from /document):
- Properties:
dpi,hostDpi,password,colourSpace,format,loadMode
Confirmed patterns:
alert(string)is a global — shorthand for a simple message dialognode.getSpreadBaseBox()returns aRectanglewith.x,.y,.width,.height,.centreUnitType.Millimetre(singular) — all unit names are singular (Pixel,Millimetre,Point)result == DialogResult.Ok— loose==equality is idiomatic;.equals()also works