@homedev/objector
v1.3.51
Published
object extensions for YAML/JSON
Downloads
757
Readme
@homedev/objector
Object processing library for YAML/JSON with support for includes, field processors, conditional logic, and extensibility.
Overview
Objector is a comprehensive tool for loading, processing, and transforming YAML/JSON documents with advanced features like:
- 🔄 Document includes and composition
- 🔌 Extensible field processors and data sources
- 🎯 Conditional logic and flow control
- 📦 Module system with custom functions
- 🔍 Variable substitution and selectors
- 📝 Output generation and file writing
- 🎨 Template inheritance and extensions
Installation
bun add @homedev/objector
# or
npm install @homedev/objector
# or
pnpm add @homedev/objectorQuick Start
import { Objector } from '@homedev/objector'
const objector = new Objector()
// Load and process a YAML/JSON file
const result = await objector.load('config.yaml')import { Objector } from '@homedev/objector'
const objector = new Objector()
.variables({ env: 'production', version: '1.0.0' }) // Add custom variables
.include('settings.yaml') // Include additional files
// Process the document
const processed = await objector.load('main.yaml')Built-in Keys
Keys are object properties prefixed with . and are used for structure/flow control.
.output- Register output payload(s).load- Load one or more additional files.each- Repeat a model over a source list.map- Map a source list into a transformed list.from- Resolve a selector/reference into current node.concat- Concatenate arrays from selectors.extends- Merge from one or many templates.group- Expand grouped items into parent list.if- Conditional branch using.then/.else.switch- Case-based branching withcases/default.skip- Remove parent when condition is true.metadata- Attach metadata for a path.modules- Register source functions from inline JS modules.try- Guard expression with optional.catch.let- Introduce temporary variables into context.tap- Debug current path/value to console
Built-in Data Sources
Sources are used with $() syntax.
Core Sources
- Files:
include,exists,file,scan - String/format:
substring,repeat,pad,formatAs - List:
merge,join,range,filter - Conditions:
if,check,and,or,xor,true,false,eq,ne,lt,le,gt,ge,in,notin,contains,notcontains,containsi,notcontainsi,null,notnull,empty,notempty,nullorempty,notnullorempty - Types:
convert,isType,typeOf - Flow helpers:
each,switch,default
Built-in Macro Sources
These are also available as $() sources by default.
- String/text:
env,uuid,pascal,camel,capital,snake,kebab,len,reverse,concat,trim,ltrim,rtrim,lower,upper,encode,decode - Collection/object:
list,object,unique,groupBy,chunk,flatten,compact,head,tail - Path/filepath:
pathJoin,resolve,dirname,basename,normalize,extname,relative,isAbsolute,segments - Hash/encoding:
md5,sha1,sha256,sha512,hash,hmac,base64Encode,base64Decode,hexEncode,hexDecode - Math:
add,subtract,multiply,divide,modulo,power,sqrt,abs,floor,ceil,round,min,max,clamp,random - Date/time:
timestamp,iso,utc,formatDate,parseDate,year,month,day,dayOfWeek,hours,minutes,seconds - Regex:
regexTest,regexMatch,regexMatchAll,regexReplace,regexReplaceAll,regexSplit,regexExec,regexSearch - Validation/predicates:
isEmail,isUrl,isJson,isUuid,minLength,maxLength,lengthEquals,isNumber,isString,isBoolean,isArray,isObject,isEmpty,isTruthy,isFalsy,inRange,matchesPattern,includes,startsWith,endsWith - Debug:
log
API Reference
Objector Class
Constructor
const objector = new Objector()Configuration Methods
use(handler: (o: Objector) => void): this
Apply a configuration handlerincludeDirectory(...dirs: string[]): this
Add directories to search for includesinclude(...files: string[]): this
Add include files directlykeys(keys: FieldProcessorMap): this
Add or override key processorssources(sources: FieldProcessorMap): this
Add or override data sourcesvariables(vars: Record<string, any>): this
Set global variablesfieldOptions(options: ProcessFieldsOptions): this
Customize field processing behaviorfilter(f: RegExp): this
Add a filter for field processingoutput(o: Output): this
Add an output definitionmetadata(path: string, value: unknown): this
Store metadata for a pathencoders(encoders: Record<string, Encoder>): this
Add output encoders (used byformatAs)decoders(decoders: Record<string, LoadFormatParser>): this
Add input decoders forload()setCacheMaxSize(size: number): this
Set include/content cache sizeclearCache(): this
Clear cached loaded content
Processing Methods
async load<T>(fileName: string, cwd?: string, container?: any, noProcess?: boolean): Promise<T | null>
Load and process a fileasync loadObject<T>(data: T, container?: any, options?: LoadObjectOptions): Promise<T>
Process an object with field processorsasync writeAll(options?: WriteOutputsOption): Promise<void>
Write all registered outputs to disk
Query Methods
getIncludeDirectories(): string[]
Get all include directoriesgetFunctions(): Record<string, AsyncFunction>
Get registered functionsgetOutputs(): Output[]
Get all registered outputsgetMetadata(path: string): any
Get metadata for a pathgetAllMetadata(): Record<string, any>
Get all metadatagetCurrentContext(): LoadContext | null
Get current processing contextgetEncoder(name: string): Encoder | undefined
Get an encoder by namegetDecoder(name: string): LoadFormatParser | undefined
Get a decoder by name
Advanced Usage
Custom Data Sources
import { Objector } from '@homedev/objector'
const objector = new Objector()
objector.sources({
// Simple value source
timestamp: () => Date.now(),
// Source with arguments
add: (ctx) => {
const [a, b] = ctx.args
return a + b
},
// Async source
fetchData: async (ctx) => {
const url = ctx.args[0]
const response = await fetch(url)
return response.json()
}
})Usage:
data:
created: $(timestamp)
sum: $(add:10, 20)
remote: $(fetchData:"https://api.example.com/data")Custom Key Processors
objector.keys({
// Custom transformation key
uppercase: (ctx) => {
return ctx.value.toUpperCase()
},
// Conditional key
when: (ctx) => {
const condition = ctx.value
if (!condition) {
return NavigateResult.DeleteParent()
}
return NavigateResult.DeleteItem()
}
})Usage:
settings:
name:
.uppercase: hello world
# Result: "HELLO WORLD"
feature:
.when: $(eq:env, "production")
enabled: true
# Only included when condition is trueMetadata Collection
const objector = new Objector()
// Metadata is collected during processing
await objector.load('config.yaml')
// Retrieve metadata
const metadata = objector.getMetadata('some.path')
const allMetadata = objector.getAllMetadata()In documents:
service:
.metadata:
version: 1.0
author: team-a
name: api
port: 8080FAQ
Q: How do I debug field processing?
A: Use the $(log:message) data source to print values during processing.
Q: Can I use async operations in custom sources?
A: Yes! All field processors and data sources support async/await.
Q: How do I handle circular includes?
A: The system tracks included files to prevent circular dependencies.
Q: Can I extend the built-in processors?
A: Yes, use objector.keys() and objector.sources() to add or override processors.
Q: How do I access nested values?
A: Use the selector syntax: $(some.nested.value) or $(@root.some.value) for root access.
Q: What's the difference between keys and sources?
A: Keys are prefixed with . and control structure/flow (.if, .each). Sources use $() syntax and provide values ($(env:VAR), $(file:path)).
