JSOS - JavaScript Object Schema
About
This package includes a parser and transformer for this custom JS object schema structure.
Installation
yarn add -D jsos
Usage
jsosParser
The parser receives the JS object schema definition and creates an abstract tree.
Example
const definitions = {
colors: {
blue: {
100: '#00f',
},
},
};
const elements = jsosParser(definitions);
The generated tree becomes:
[
{
"type": "NodeType",
"path": "",
"value": [
{
"type": "NodeType",
"path": "colors",
"value": [
{
"type": "NodeType",
"path": "colors.blue",
"value": [
{
"type": "StringType",
"path": "colors.blue.100",
"value": "#00f"
}
]
}
]
}
]
}
]
Elements types
interface JSOSParserNodeElement {
type: 'NodeType';
path: string;
value: JSOSParserElement[];
}
interface JSOSParserStringElement {
type: 'StringType';
path: string;
value: string;
}
interface JSOSParserNumericElement {
type: 'NumericType';
path: string;
value: number;
}
interface JSOSParserListElement {
type: 'ListType';
path: string;
value: JSOSParserElement[];
}
interface JSOSParserBooleanElement {
type: 'BooleanType';
path: string;
value: boolean;
}
interface JSOSParserNullishElement {
type: 'NullishType';
path: string;
value: null;
}
Other types:
interface JSOSParserRootElement {
type: 'NodeType';
path: '';
value: JSOSParserElement[];
}
type JSOSParentElement =
| JSOSParserNodeElement
| JSOSParserListElement;
type JSOSPrimitiveElement =
| JSOSParserStringElement
| JSOSParserNumericElement
| JSOSParserNullishElement
| JSOSParserBooleanElement;
jsosTransformer
The transformer is responsible for navigating through the tree generated by the parser and transform it into something useful. It accepts a tree as the first argument and a set of options as the second.
To transform the tree, you can pass transformer functions to through the option object's transformers
in the form of an object:
{
transformers: {
NodeType() { /* ... */ },
StringType() { /* ... */ },
NumericType() { /* ... */ },
ListType() { /* ... */ },
BooleanType() { /* ... */ },
NullishType() { /* ... */ },
}
}
Note: To define your transformers, you can import the
NODE_TYPE
,STRING_TYPE
,NUMERIC_TYPE
,LIST_TYPE
,BOOLEAN_TYPE
andNULLISH_TYPE
variables and use them to define the keys.
Example
const elements = jsosParser(definitions);
const content = jsosTransformer(elements, {
transformers: {
[STRING_TYPE](element, { content, parseValue }) {
content.append(
`--${element.path.split('.').join('-').toLowerCase()}: ${parseValue(
element.value,
)};`,
);
},
},
});
Results in:
--colors-blue-100: #00f;
jsosTransformer options
interface JSOSTransformerOptions<T = Record<string, any>> {
valueParsers: Record<string, ValueParser>;
transformers: Partial<
Record<JSOSParserElementType, JSOSTransformerFunction<T>>
>;
makeContext?(context: JSOSTransformerContext): T;
context: JSOSTransformerContext | (JSOSTransformerContext & T);
initialValue: string | Record<string, any>;
}
Transformers' context
interface JSOSTransformerContext {
elements: JSOSParserElement[];
transform: JSOSTransformer;
transformers: Record<JSOSParserElementType, JSOSTransformerFunction>;
parseValue: ParseValue;
content: Content;
findByPath(
path: string,
elements?: JSOSParserElement[],
): JSOSParserElement | undefined;
}
The content is a class that contains the transpiled content. To modify the content you can use:
// If the initialValue is a string or undefined
interface StringContent {
value: string;
append(value: string): this;
prepend(value: string): this;
}
// If the initialValue is an object
interface ObjectContent {
value: Record<string, any>;
append(path: string, value: any): this;
prepend(path: string, value: any): this;
}
Test coverage
92.55% | Statements | 298/322 |
73.77% | Branches | 135/183 |
83.56% | Functions | 61/73 |
92.39% | Lines | 255/276 |