npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

datamatic

v0.9.13

Published

RxJS + JSON-Schema (Ajv) Based Observable and Validating Data Models and Pipelines

Downloads

16

Readme

Datamatic

RxJS + JSON-Schema (Ajv) Based Observable and Validating Data Models and Pipelines

Build Status Codacy Badge Codacy Badge Maintainability

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

Usage Examples

Developer Guide

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 |