datamatic
v0.9.13
Published
RxJS + JSON-Schema (Ajv) Based Observable and Validating Data Models and Pipelines
Downloads
16
Maintainers
Readme
Datamatic
RxJS + JSON-Schema (Ajv) Based Observable and Validating Data Models and Pipelines
Online Developer Documentation
Goals
- Provide a means to quickly and easily validate complex data-sets
- Look and feel like a standard JS Object for ease of use and adaptability
- Automate data evaluation and transformation
Table of Contents
Installation Instructions
$ npm install datamatic
UMD Usage (React, Angular, Vue et al)
import * as datamatic from "datamatic";
CommonJS Usage for NodeJS
const {Model, Pipeline} = require("datamatic");
DOM Window Usage
<script src="../../dist/datamatic.window.js"></script>
<script language="JavaScript">
const {Model, Pipeline} = window.datamatic;
</script>
Usage Examples
Basic Example
The example below defines a Model that expects a name
value and
list of topScores
items
const {Model} = require("datamatic");
// JSON-SCHEMA for Scores Collection
const schema = {
"id": "root#",
"type": "object",
"properties": {
"name": {
"type": "string",
},
"topScores": {
"type": "array",
"minItems": 1,
"maxItems": 3,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"score": {
"type": "integer",
"default": 0
}
},
"required": ["name"]
}
}
},
required: ["name", "topScores"],
};
// instantiate our Model
const obj = new Model({schemas: [schema]});
// subscribes an observer to the Model
obj.subscribe({
next: function (ref) {
console.log("\t>> update succeeded!\n\t%s\n\t%s\n\n",
"current object state:", "" + JSON.stringify(ref));
},
complete: function (ref) {
console.log("\t>> %s",
"object is frozen and no longer editable");
},
error: function (e) {
console.log("\t>> update FAILED with error:\n\t%s\n",
JSON.stringify(e));
console.log("\tcurrent object state:\n\t%s\n", obj);
},
});
// populate the Model with data
// -- this will trigger the "next" notification
obj.model = {
name: "JSONville",
topScores: [{
name: "Player 1",
score: 12300000,
}, {
name: "Player 2",
score: 45600000,
}, {
name: "Player 3",
score: 78900000,
}]
};
// update the model
// this will trigger the next notification
obj.model.topScores[0].score++;
// invalid attempt update the model
// this will trigger the error notification
// reason: "topScores/items/score" is type is integer
obj.model.topScores[0].score = "1234";
// invalid attempt update the model
// this will trigger the error notification
// reason: "topScores" is marked as required
delete obj.model.topScores;
Refer to the examples demo in ./examples/basic-usage
for more usage examples
Data Pipelines and Transformation
const {Pipeline} = require("datamatic");
/*
defines a schema that requires name, age and active attributes
filters out all items that do not conform to JSON-Schema below
*/
const schema = {
type: "object",
required: ["name", "age", "active"],
properties: {
name: {
$comment: "names must be in form: First Middle|MI Last",
type: "string",
pattern: "^[a-zA-Z]{1,24}\\s?[a-zA-Z]?\\s+[a-zA-Z]{1,24}$",
},
age: {
$comment: "age must be a number equal to or higher than 21 and lower than 100",
type: "number",
minimum: 21,
maximum: 100,
},
active: {
$comment: "active must equal true",
type: "boolean",
const: true,
},
},
};
const pipeline = new Pipeline(
[
// By nesting an item schema within an iterator, the schema is applied as a filter
schema,
// the list can go on ...
],
// the list can go on ...
);
pipeline.subscribe({
// should only contain active people who are 21 and over and name pattern match
next: (d) => console.log(`\nfiltered results:\n${JSON.stringify(d)}`),
// it should not encounter an error unless it is critical, so full stop
error: (e) => console.error(`\ngot error:\n${JSON.stringify(e)}`),
});
pipeline.write([
{name: "Alice Dodson", age: 30, active: false}, // will be filtered because of active status
{name: "Jim-Bob", age: 21, active: true}, // will be filtered because of name format
{name: "Bob Roberts", age: 38, active: true}, // will pass
{name: "Chris Appleton", age: 19, active: true}, // will be filtered because of age
{name: "Fred Franks", age: 20, active: true}, // will be filtered because of age
{name: "Sam Smith", age: 25, active: true}, // will pass
{name: "", active: null}, // will be filtered because of invalid object format
]);
Developer Guide
Model Class
This class represents the Document entry point
| Method | Arguments | Description | |:--------------|:----------|:-------| | constructor | schemas config (object), [options (object)] | creates new Model instance | | errors [getter] | | retrieves errors (if any) from last json-schema validation | | model [getter/setter] | | retrieves root model proxy object for operation | | getModelsInPath | to (string) | retrieves models at given path | | getSchemaForKey | key (string) | retrieves json-schema with given key as ID | | getSchemaForPath | path (string) | retrieves json-schema for model at given path | | schema [getter] | | retrieves json-schema for root model | | subscribe | observers (object) | Subscribes Observers to the Model Model Root | | subscribeTo | path (string), observers (object) | Subscribes Observers to the Model at path | toString | | retrieves root model as JSON String | | toJSON | | retrieves root model as JSON Object | | validate | path (string), value (object) | validates data at given ath against JSON-Schema | | static fromJSON | json (string | object) | creates new Model from static method |
Model Schemas Config
| Property | Type | Description | |:--------------|:----------|:-------| | meta | array | Array of MetaSchema references to validate Schemas against | schemas | array | Array of Schema references to validate data against | use | string | key/id of schema to use for data validation
Model Proxy Object
This is the Data Model most usage will be based around. It is a Proxy Object that has traps for all operations that alter the state of the given Array or Object
| Property | Type | Description | |:--------------|:----------|:-------| | $model | (PropertiesModel | ItemsModel) | references Proxy Object owner class
model vs $model
In usage, model
always references the Proxied Data Model for validation and operation where $model
references the owner Model Class
example:
const _owner = new Model({schemas: [schema]});
// access the root model:
console.log(`JSON.stringify(_owner.model)`);
// access the model's owner Model Class:
const owner = _owner.model.$model;
console.log(`is frozen: ${owner.isFrozen}`);
// call toString on Owner
console.log(`stringified: ${owner}`);
// obtain model from it's Owner
console.log(`stringified: ${JSON.stringify(owner.model)}`);
ItemsModel
subclass of Model Class
Represents an Items (Array) entry in the given schema
Note: the model
param presents a Proxied Array, with all Array.prototype
methods trapped and validatable
| Method | Arguments | Description | |:--------------|:----------|:-------| | model [getter/setter] | | setter/getter for model proxy object for operation |
PropertiesModel
subclass of Model Class
Represents an Properties (Object} entry in the given schema
| Method | Arguments | Description | |:--------------|:----------|:-------| | get | key (string) | applies Object.freeze to model hierarchy | | model [getter/setter] | | setter/getter for model proxy object for operation | | set | key (string), value (any) | applies Object.freeze to model hierarchy |
BaseModel Class
| Method | Arguments | Description | |:--------------|:----------|:-------| | freeze | | applies Object.freeze to model hierarchy | | isDirty [getter] | | returns dirtyness of model heirarchy (is dirty if operation in progress) | | isFrozen [getter] | | returns Object.freeze status of Model hierarchy | | jsonPath [getter] | | retrieves json path string for Model instance. eg: "this.is.my.path" | | objectID [getter] | | retrieves Unique ObjectID of Model instance | | options [getter] | | retrieves options passed to Model instance | | path [getter] | | retrieves json-schema path string for Model instance. eg: "#/this/is/my/path" | | parent [getter] | | retrieves Model's parent Model instance | | pipeline | ...(pipes | schemas) | returns Pipeline instance for operating on model | | reset | | resets model to initial state if operation is valid | | root [getter] | | retrieves root Model instance | | model [getter] | | retrieves Model's internal Model Document instance | | subscribe | observers (object) | Subscribes Observers to the Model Model Root | | subscribeTo | path (string), observers (object) | Subscribes Observers to the Model at path | | toString | | retrieves root model as JSON String | | toJSON | | retrieves root model as JSON Object | | validate | path (string), value (object) | validates data at given ath against JSON-Schema | | validationPath [getter] | | retrieves json-schema path string for Model validation |
Pipeline Class
| Method | Arguments | Description |
|:--------------|:----------|:-------|
| constructor | ...pipesOrSchemas | class constructor method |
| errors [getter] | | retrieves errors (if any) from last json-schema validation |
| exec | data (object | array | string | number | boolean)| executes pipeline's callback with data without writing to pipeline
|
| subscribe | handler (object | function | schema | array)| subscribes to pipeline
output notifications |
| toJSON | | Provides current state of pipeline
output as JSON |
| toString | | Provides current state of pipeline
output as JSON string |
| clone | | returns clone of current pipeline
segment |
| close | | terminates input on pipeline
segment |
| writable [getter] | | Returns write status of pipeline
|
| link | target (Pipeline), ...pipesOrSchemas | links pipeline
segment to direct output to target pipeline
|
| merge | ...(pipes | schemas) | merges multiple pipes into single output |
| once | | informs pipeline
to close after first notification |
| pipeline | ...(pipes | schemas) | returns new chained pipeline
segment |
| sample | nth | Returns product of Nth occurrence of pipeline
execution |
| split | ...(pipes | schemas) | creates array of new pipeline
segments that run in parallel |
| tap | | Provides current state of pipeline
output. alias for toJSON
|
| throttle | rate (number) | Limit notifications to rate based on time interval |
| unthrottle | discardCacheQueue (boolean) | Clears throttle interval. Optionally discards contents of Pipeline
cache |
| unlink | target (Pipeline)| unlinks pipeline
segment from target pipeline
|
| write | data (object | array | string | number | boolean)| writes data to pipeline
|