Skip to main content

Programmatic API

Sassy exposes its core classes for programmatic use. As of v5, the API uses a builder pattern for Theme and provides standalone engine classes (Lint, Resolve, Proof) that work without CLI infrastructure.

Installation

TERMINAL
  npm install @gesslar/sassy

Package Exports

SpecifierPurpose
@gesslar/sassyProgrammatic API (all exported classes)
@gesslar/sassy (bin)CLI entry point (sassy command)

Basic Usage

javascript
  import {FileObject, DirectoryObject} from '@gesslar/toolkit'
import {Theme} from '@gesslar/sassy'

const cwd = DirectoryObject.fromCwd()
const file = cwd.getFile('my-theme.yaml')

const theme = new Theme()
.setCwd(cwd)
.setThemeFile(file)
.withOptions({outputDir: './dist'})

await theme.load()
await theme.build()

const output = theme.getOutput() // compiled theme object
await theme.write() // write to disk
tip

Cache is optional. Without one, load() reads the file directly via FileObject.loadData(). Set a cache with .setCache(cache) before load() when you want cross-theme file caching in a session.

tip

Engine methods will automatically call theme.load() if the Theme is not ready. They do not automatically call theme.build(), so build first when you need compiled output (e.g. Resolve, full linting).

Exported Classes

Engine classes are the preferred API surface for programmatic consumers. They have no CLI dependencies — give them a compiled Theme and they return structured data.

ExportDescription
ThemeTheme lifecycle: load, build, write, dependency tracking
LintLint engine — static analysis, returns structured issue data
ResolveResolve engine — token/scope resolution with trails
ProofProof engine — composed document view (pre-evaluation)
ColourColour manipulation utilities (lighten, darken, mix, etc.)
YamlSourceYAML source tracking — maps compiled output back to source locations

Theme Class

Builder Pattern

Theme uses a chainable builder. All setters return this.

javascript
  const theme = new Theme()
.setCwd(cwd) // DirectoryObject
.setThemeFile(file) // FileObject
.withOptions({outputDir: './dist'}) // compilation options
.setCache(cache) // optional Cache instance
Builder MethodTypeDescription
setCwd(dir)DirectoryObjectWorking directory for relative path resolution
setThemeFile(file)FileObjectSource theme file (also derives theme name)
withOptions(opts)objectCompilation options (outputDir, dryRun, silent, nerd)
setCache(cache)CacheFile cache instance (optional — load() falls back to direct file read)

Methods

MethodReturnsDescription
load()Promise<this>Parse and validate the source file
build()Promise<this>Run the full compilation pipeline
write(force?)Promise<{status, file}>Write output to disk. Skips if hash unchanged unless force is true.
reset()voidClear compiled state for rebuild
getOutput()object | nullGet the compiled theme object
getPool()ThemePool | nullGet the variable resolution pool
getName()stringGet the theme name (derived from filename)
getSource()object | nullGet the parsed source data
getDependencies()SetGet tracked file dependencies
addDependency(file, source)thisTrack an import dependency
hasOutput()booleanCheck if compilation produced output
isReady()booleanCheck if source data is available
isCompiled()booleanCheck if output, pool, and lookup are present
findSourceLocation(path)string | nullLook up the source file, line, and column for a dot-path in the compiled theme, formatted as file:line:col

Lint Engine

The Lint class analyses a compiled theme and returns structured issue data. No CLI infrastructure needed.

javascript
  import {DirectoryObject} from '@gesslar/toolkit'
import {Theme, Lint} from '@gesslar/sassy'

const cwd = DirectoryObject.fromCwd()
const file = cwd.getFile('my-theme.yaml')

const theme = new Theme()
.setCwd(cwd)
.setThemeFile(file)
.withOptions({})
await theme.load()
await theme.build()

const results = await new Lint().run(theme)
// results.tokenColors - array of tokenColors issues
// results.semanticTokenColors - array of semanticTokenColors issues
// results.colors - array of colors issues
// results.variables - array of variable issues
//
// Each issue object includes a location property (string):
// "path/to/file.yaml:42:5"

Constants for issue types, severity levels, and section names are static properties on Lint:

javascript
  Lint.SECTIONS.TOKEN_COLORS        // "tokenColors"
Lint.SEVERITY.HIGH // "high"
Lint.ISSUE_TYPES.DUPLICATE_SCOPE // "duplicate-scope"

Proof Engine

The Proof class returns the fully composed theme document (post-import, pre-evaluation).

javascript
  import {DirectoryObject} from '@gesslar/toolkit'
import {Theme, Proof} from '@gesslar/sassy'

const cwd = DirectoryObject.fromCwd()
const file = cwd.getFile('my-theme.yaml')

const theme = new Theme()
.setCwd(cwd)
.setThemeFile(file)
.withOptions({})
await theme.load()

const composed = await new Proof().run(theme)
// composed.config - resolved config (without import key)
// composed.palette - merged palette with séance inlined
// composed.vars - merged vars
// composed.theme.colors - merged colors
// composed.theme.tokenColors - appended tokenColors
// composed.theme.semanticTokenColors - merged semanticTokenColors

Resolve Engine

The Resolve class traces token resolution through the variable dependency chain.

javascript
  import {DirectoryObject} from '@gesslar/toolkit'
import {Theme, Resolve} from '@gesslar/sassy'

const cwd = DirectoryObject.fromCwd()
const file = cwd.getFile('my-theme.yaml')

const theme = new Theme()
.setCwd(cwd)
.setThemeFile(file)
.withOptions({})
await theme.load()
await theme.build()

const resolver = new Resolve()

// Resolve a colour variable
const colorResult = await resolver.color(theme, 'editor.background')

// Resolve a tokenColors scope
const tokenResult = await resolver.tokenColor(theme, 'keyword.control')

// Resolve a semanticTokenColors scope
const semanticResult = await resolver.semanticTokenColor(theme, 'variable')

resolve(theme, options)

ParameterTypeDescription
themeThemeA compiled theme (must have been loaded and built)
optionsobjectExactly one of the keys below
Option KeyTypeDescription
colorstringA colour property key (e.g. editor.background)
tokenColorstringA tokenColors scope (e.g. keyword.control)
semanticTokenColorstringA semanticTokenColors scope (e.g. variable)

The three options are mutually exclusive — pass exactly one per call.

Return Value

The method returns an object whose shape depends on the resolution type and outcome.

Colour resolution (color):

FieldTypeDescription
foundbooleanWhether the colour key exists in the theme
namestringThe requested colour key
resolutionstringFinal resolved hex value (when found)
trailarrayResolution steps, each with value, type, and depth

Scope resolution (tokenColor / semanticTokenColor):

FieldTypeDescription
foundbooleanWhether a matching scope was found
namestringThe requested scope
ambiguousbooleantrue when multiple entries match and disambiguation is needed
matchesarrayAvailable disambiguations (when ambiguous)
entryNamestringThe matched tokenColors entry name
resolutionstringFinal resolved hex value
resolvedViaobjectPresent when resolved through precedence fallback (scope, relation)
noForegroundbooleantrue when the matched entry has no foreground property
staticbooleantrue when the value is a static literal (no variable resolution)
trailarrayResolution steps, each with value, type, and depth