@sprucelabs/spruce-skill-utils
v34.0.25
Published
Loosely coupled classes and functions to make skill development faster! 🏎
Downloads
17,827
Readme
Spruce Skill Utils
Utilities and services used across Spruce skills and tooling. Exports are available from src/index.ts.
Utilities
buildLog (Logging)
Structured logger with prefixes, transports, time decorations, log gating, and history tracking.
Quick start
import buildLog from '@sprucelabs/spruce-skill-utils'
const log = buildLog('APP', { useColors: false })
log.info('booting')
log.warn('cache miss', { key: 'users:1' })
log.error('boom', new Error('Something failed'))Prefixes and hierarchy
Prefixes are chained via buildLog. Returned strings include the prefixes, and transports receive the prefix as a separate first argument.
const root = buildLog('ROOT', { useColors: false })
root.info('message')
const child = root.buildLog('CHILD')
child.error('an error occurred')Outputs:
(INFO) ROOT :: message(ERROR) ROOT :: CHILD :: an error occurred
Maximum prefix length
Use MAXIMUM_LOG_PREFIXES_LENGTH to limit how many prefix segments are included.
process.env.MAXIMUM_LOG_PREFIXES_LENGTH = '2'
const log = buildLog('ONE')
.buildLog('TWO')
.buildLog('THREE')
log.info('value')Transport receives: TWO :: THREE :: value
Set to 0 to suppress prefixes entirely.
Log level gating
Control which levels are emitted using LOG_LEVEL.
process.env.LOG_LEVEL = 'warn'
const log = buildLog('APP', { useColors: false })
log.info('info message')
log.warn('warn message')
log.error('error message')With LOG_LEVEL=warn, only warn and error are emitted.
Time decorations
By default, log output includes a timestamp and a time-since-last-log delta. Disable with env flags.
process.env.SHOULD_LOG_TIME = 'false'
process.env.SHOULD_LOG_TIME_DELTAS = 'false'
const log = buildLog('TIMESTAMPS', { useColors: false })
log.info('first')Transports
You can route logs per level to custom transports. Transports receive prefix and args only (no (INFO) or timestamps).
let infoMessage = ''
let errorMessage = ''
const log = buildLog('TEST', {
useColors: false,
transportsByLevel: {
INFO: (...parts) => { infoMessage = parts.join(' ') },
ERROR: (...parts) => { errorMessage = parts.join(' ') },
},
})
log.info('go team')
log.error('error me')Captured values:
infoMessagebecomesTEST :: go teamerrorMessagebecomesTEST :: error me
You can also provide multiple transports per level:
const log = buildLog('MULTI', {
transportsByLevel: {
INFO: [
(...parts) => console.log('one', parts.join(' ')),
(...parts) => console.log('two', parts.join(' ')),
],
},
})Custom log override (rare)
If you provide log, it overrides the output target entirely (no console/stderr). This is typically only useful in tests.
const log = buildLog('NOOP', { useColors: false, log: () => {} })
log.info('this returns a string, but nothing is emitted')Colors and TTY
Colors are enabled only when stdout.isTTY is true and useColors !== false.
process.stdout.isTTY = false
const log = buildLog('TTY', {})
log.info('go team')Output: (INFO) TTY :: go team
Prefix-based logging control
If isMainModule() is false, logging is disabled unless SPRUCE_LOGS includes the logger’s prefix.
process.env.SPRUCE_LOGS = 'Billing,Auth'
const log = buildLog('Auth', { useColors: false })
log.info('allowed')History tracking
Logging history is shared across all logger instances.
const log = buildLog()
log.startTrackingHistory(2)
log.info('one')
log.info('two')
log.info('three')
log.getHistory()History contains: ["two", "three"]
API
buildLog(prefix?: string, options?: LogOptions): LogLoggerclass (implementsLog)testLogandstubLog
testLog
Logger preconfigured to write to stderr. Useful in tests.
stubLog
Logger preconfigured to do nothing. Colors disabled.
diskUtil
Filesystem helper utilities.
Key behaviors
resolvePathresolves relative paths to a cwd and expands#spruceto.spruce.resolveFilesearches for bare,.js, and.tsfiles in order.hasFileChangedtracks file changes using.change_cacheand a.gitignorein that cache directory.deleteEmptyDirsremoves empty directories recursively and validates inputs.detectProjectLanguageinfersts,js,go, orunknown.
versionUtil
Versioned-path helper that works with vYYYY_MM_DD directories and {{@latest}} tokens.
Key behaviors
resolvePathreplaces{{@latest}}with the latest version directory.resolveNewLatestPathcreates a new latest path using today’s date.getAllVersionsreturns sorted version metadata.latestVersionAtPaththrows if no versioning exists.
namesUtil
String and naming helpers.
API
toFileNameWithoutExtensiontoCameltoPascaltoConsttoPluraltoSingulartoKebabtoSnake
addonUtil
Discovers and loads *.addon.[t|j]s files.
Key behaviors
importloads all addons under a path and awaits results.importSyncloads all addons synchronously.- If a module has a default export function, it is invoked with
options.
pluginUtil
Discovers and loads *.plugin.[t|j]s files.
Key behaviors
importloads plugins asynchronously and returns their results.importSyncloads plugins synchronously and validates inputs.- Plugins must export a default function or an error is thrown.
randomUtil
Random selection helper.
API
rand<T>(possibilities: T[]): T
joinIntoSentence
Joins words into a human-readable sentence with an & before the last item.
Example
['hey', 'there']→hey & there['a', 'b', 'c']→a, b & c
slug
Creates a lowercase, dash-separated slug from an input string.
cloneDeep
Deprecated wrapper around @sprucelabs/schema cloneDeep. Prefer importing directly from @sprucelabs/schema.
isEqual
Deep equality check with special handling for Date and with null/undefined field removal.
Renderers
locationRenderer
Renders an AddressFieldValue into a single, trimmed line with missing fields omitted.
Services
SettingsService
Persists feature flags and settings to a JSON file under .spruce.
Key behaviors
- Supports
markAsInstalledandmarkAsPermanentlySkipped. - Supports nested
get,set, andunset. - Uses
.spruce/settings.jsonfor JS/TS projects and.spruce/settings.jsonin the repo root for Go projects. - Supports custom settings filename via
setFile.
EnvService
Reads and writes a .env file in the current working directory.
Key behaviors
setwrites literals with quoting and escapes newlines.getcoerces booleans and integers.unsetremoves keys from both the file andprocess.env.
PkgService
Reads and writes package.json.
Key behaviors
get,set, andunsetfor package fields.doesExistchecks forpackage.json.isInstalledchecks dependencies and devDependencies.deleteLockFileremovespackage-lock.jsonandyarn.lock.buildPackageNameformatsname@version.
AuthService
Manages local auth state for skills.
Key behaviors
Auth(cwd)validates apackage.jsonexists and returns a service instance.- Persists a logged-in person to
~/.spruce/person.json. - Reads and updates current skill credentials from
.envandpackage.json. - Normalizes and validates person data against a schema.
Types and constants
Exports include Skill, SkillAuth, PersonWithToken, EnvValue, and constants such as HASH_SPRUCE_DIR, LATEST_HANDLEBARS, and CORE_SCHEMA_VERSION.
