codata
v1.6.0
Published
Data-centric code exec utility
Downloads
15
Readme
Codata
YAML & OOP (multiple inheritance supported) based data utility with JS hooks. For example: config A extends config B, which extends config C, and every of them can exec associated JS script.
More specifically - Config A deepmerge with its super config B, which deepmerge with super config C. After each config parsed, JS hook can be executed to apply some modifications which much easier to do with JS rather than with any kind of templating language. Basic templating implemented too BTW... Before parse supported data types (Yaml & Json for now), utility search and replace placeholders like ${VAR}
Configs organized in 'modules'. Module addressed by name, and stored in a file with according or shortened name. Module 'project_beta' can be described in a file project_beta.[yaml|json] or in a file project.[yaml|json]. It is useful for multi-environment system with a lot of similar configs.
Install & test
$ npm install codata
$ npm run test
Usage
Assume that you have _general.yaml, _general.js, project.yaml & project.js files in ./codata folder (can be changed with codata.pathToModules) with following content:
_general.yaml:
_general:
__constructor: _general.js
templatingTest: from _general.yml ${PROJECT}
someJSValues:
- general.yaml
worker:
replicas: 10
_general.js:
export let _general = function (){ // function with module`s name
this.someJSValues.push ('General');
}
project.yaml:
project:
__extends: _general
__constructor: project.js
title: Project
worker:
replicas: 1
project_beta:
__extends: project
__constructor: project.js
title: Project (BETA)
project.js:
export let project = function () { // function with module`s name
this.someJSValues.push ('Project');
}
export let project_beta = function () { // function with module`s name
this.someJSValues.push ('Project_beta');
}
In this case, we can get resulting config for modules '_general', 'project' & 'project_beta'. Config for 'project_beta' will contain following (note that __constructor
& __extends
fields are removed):
{
templatingTest: 'from _general.yml My Project' // from _general
someJSValues: ['general.yaml', 'General', 'Project', 'Project_beta'] // code execution order
worker: {replicas: 1} // from 'project'
title: 'Project (BETA)' // from 'project_beta'
}
To achieve that just load data with this code:
import codata from "codata";
codata.templatingData = {PROJECT: 'My project'}; // process.env by default
let data = await codata.load ('project_beta');
Instantiate your own instance:
import {Codata} from "codata";
let cd = new Codata ();
cd.modulesSplitBy = '_'
cd.pathToModules = '/usr/data/';
let data;
let data = await cd.load ('project_beta');
Codata basics
Codata operates with 'modules'. Each module have a unique name. Modules stored in Yaml files. One Yaml file may contain many of modules with according names. Module name in file should be the same as filename, or include filename as a part.
For example:
- Module
sockets
must be placed in filesockets.yaml
- Module
sockets_ssl
can be placed in one of filessockets_ssl.yaml
orsockets.yaml
- Module
sockets_ssl_v2
can be placed in one of filessockets_ssl_v2.yaml
orsockets_ssl.yaml
orsockets.yaml
Config file format specials
File options
local
- Define variables witch is accessible only inside this file with ${local.varName} syntax__environment
- Define or redefine ENV variables witch is accessible inside this file and all included modules as well with ${env.varName} syntax. . See __environment variables
Module options
__extends
- Module or array of modules, which should be deepmerge with current module. See __extend formats__environment
- Define or redefine ENV variables
Module events
Module event described in following format - filename[#function]
if #function
omitted, module's name will be used instead. Function called with module object as this
__constructor
(default: null) - Executed after current module data is parsed and before it will be deepmerge to its descendant. If constructor return any value, exceptundefined
, result will be replaced with that value.__onready
(default: null) - Executed only one last function in inheritance chain after whole module data is constructed and ready to return. If descendant have this event, it will replace such event in ancestor, and only one call will occur__script
- Deprecated analogue of__constructor
__extend formats
String
- name or path/name to module. e.g. 'myModule'[email protected]
- name of module as above. Module will be inserted not in a root of current object, but into theObject.Deep.Target
instead. See 'healthcheck-a' & 'healthcheck-b' in v1.3.0 tests{module: 'String', props: {propName: 'propValue'}}
- Include module with passing extra options (props). Options is accessible in the module with${props.propName}
syntax.
__environment variables
Here is a three level of ENV variables is available. All of that kind of variables can be accessed with ${env.varName}
syntax.
OS
- Variables defined in OS.File level
- Variables defined in file's__environment
section can define new variables or redefine OS variables.Module level
- Variables defined in module's__environment
section can define new variables or redefine OS variables and variables from file's section.
Please note (v1.5): ENV variables, once defined in loaded module, marked as final, so other definitions in included modules are ignored.