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

factom-objectdb

v0.0.3

Published

Object database implementation for the Factom protocol

Downloads

5

Readme

factom-objectdb

npm

Travis (.org)

Coveralls github

A blockchain object database implemented in NodeJS, built on Factom - all for a fraction of the cost of competitors.

This database enables basic immutable Create, Read, and Update database operations for JSON objects stored on the Factom blockchain, and features a familiar MongoDB inspired update syntax.

You can run factom-objectdb as a standalone operational database daemon(HTTP API), or use it as a library in NodeJS (see examples below)

Installation

Command Line:

git clone https://github.com/DBGrow/factom-objectdb.git

or

Using NPM:

npm -i factom-objectdb

or

In package.json:

"dependencies": {
    "factom-objectdb": "0.0.3",
}

Running As Daemon

To run factom-objectdb standalone as a daemon and API host from the command line:

cd factom-objectdb
npm start

The objectdb HTTP API will be available at port 3000 on your localhost

Config File

You can use the config.json file in the root project directory to control how the daemon runs:

{
    "apiport":3000,
    "es":"Es3k4L7La1g7CY5z....."
}

Library Examples

Initialization

Simple Initialization:

const {FactomObjectDB} = require('factom-objectdb');

const db = new FactomObjectDB({
    db_id: 'factomdbtest:0.0.1', //the ID of your database
    ec_address: 'Es3k4L7La1g7CY5zVLer21H3JFkXgCBCBx8eSM2q9hLbevbuoL6a',  //Public or private EC address
});

All configuration options:

const db = new FactomObjectDB({
    db_id: 'factomdbtest:0.0.1', //the ID of your database
    ec_address: 'Es3k4L7La1g7CY5zVLer21H3JFkXgCBCBx8eSM2q9hLbevbuoL6a',  //Public or private EC address
    factom: {
        factomd: {
        	host: '52.202.51.228',
        	port: 8088
    	},
    	walletd: {
        	host: '52.202.51.228',
        	port: 8089
    	},
        user: 'username', // RPC basic authentication
    	password: 'pwd',
    	rejectUnauthorized: true, // Set to false to allow connection to a node with a self-signed certificate
    	retry: {
        	retries: 4,
        	factor: 2,
        	minTimeout: 500,
        	maxTimeout: 2000
    	}
    }
});

Store an Object

Lets say we have an object we want to store, a person in a database:

const joe = {
    _id: '134e366520a6f93265eb',
    name: 'Joe Testerson',
    age: 30,
    best_friends: []
};

We want to store the object under unique ID 134e366520a6f93265eb (joe._id)

Saving the object permanently in Factom is as easy as:

//save the initial object to Factom!

//using async/await
const storedObject = await db.commitObject('134e366520a6f93265eb', joe);

//or using promises
db.commitObject(joe._id, joe).then(function(storedObject){
    
}).catch(function(err){
    throw err;
});

It is important to note that creation of and updates to objects take up until the next block to be reflected (up to 10 Minutes).

Get an Object

Get Joe's object using his id: 5ad28b9d18c35e2b4c000001

const joe = await db.getObject("134e366520a6f93265eb");

Retrieved Object:

{
  "_id": "134e366520a6f93265eb",
  "name": "Joe Testerson",
  "age": 25,
  "best_friends": []
}

Update an Object

This library uses a MongoDB inspired update syntax.

Currently, these operators are supported:

  • $set : Set the value of a key in the object
  • $unset : Delete the key from an object
  • $rename : Rename the key of an object
  • $inc : Increase the value of the key of an object by an amount
  • $mul : Multiply the value of the key by an number
  • $push : Add a value to the end of an array
  • $pop : Remove a value from the end of an array

Updates to Factom objects are subject to the object's Field and Object rules. Updates that do not meet the restrictions placed on the Object will be ignored when retrieving it next time. It is important to note that updates to objects take up until the next block to be reflected using getObject. Changes can take up to 10 Minutes to be reflected in the final retrieval of the object.

Let's say Joe just had his 27th birthday. We want to $set his new age:

var update = { //increase Joe's age by 1
        $set: {
            age: 27
        }
 };

await db.commitObjectUpdate("134e366520a6f93265eb", update);

Lets say Joe just made a friend named Johan! We want to $push a friend to his best_friends array:

var update = { //push a new friend to the best_friends array. Should be successful
        $push: {
            best_friends: {name: 'Yohan B', age: 30}
        }
};

await db.commitObjectUpdate("134e366520a6f93265eb", update);

Lets say Joe fell into a black hole and has aged 70 years:

var update = {
        $inc: {  //Increase Joe's age by 70!
            age: 70
        }
};

await db.commitObjectUpdate("134e366520a6f93265eb", update);

Joe is now 97 years of age, and sadly all his friends are dead. Better get rid of Johan :(

var update = { //pull a single friend from the best_friends array
        $pop: {
            best_friends: {}
        }
};

await db.commitObjectUpdate("134e366520a6f93265eb", update);

Object & Field Rules

The library allows placing restrictions on how the objects you store can be updated. The current state of an object is determined by the library using these rules when retrieving the object from Factom.

In this case, Joe Testerson is a user in a database. To facilitate that functionality, we should place some restrictions on how his object and it's fields can be updated:

let FieldRules = require('factom-objectdb/rules/FieldRules');
let ObjectRules = require('factom-objectdb/rules/ObjectRules');

//declare object rules

let objectRules = new ObjectRules.Builder()
    .setAddFields(false) //disable adding fields to Joe's object
    .setDeleteFields(false) //disable deleting fields from to Joe's object

    //declare field rules:
    .addFieldRule('_id', new FieldRules.Builder().setType('string').setEditable(false).build()) //mark Joe's ID final, so it can never be changed
    .addFieldRule('name', new FieldRules.Builder().setType('string').setEditable(true).build()) //mark Joe's name editable so he can change it later
    .addFieldRule('age', new FieldRules.Builder().setType('number').setEditable(true).setMin(0).setMax(100).build()) //Joes age is, updatable, but will be locked to non negative number <= 100
    .addFieldRule('best_friends', new FieldRules.Builder().setType('array').setEditable(true).setMax(5).build()) //limit Joe's best friends to to 5 in count, non deletable
    .build();

the field rules for the object at the same time you commit it:

//commit the initial object and rules to Factom!
const storedObject = await db.commitObject(joe._id, joe, objectRules);

Please note rules are not updatable at this time. Rule declarations for objects are permanent.

To demonstrate field rules & restrictions, Lets say Joe falls into a black hole for another 1000 years, lets do the update:

const update = {
        $inc: {
            age: 1000
        }
};

await db.commitObjectUpdate("134e366520a6f93265eb", update);

But now we have a problem! Increasing Joe's age by 1000 would make him over 1000 years old, which is over the maximum value we set for his age of 100. This update will be ignored the next time Joe's object is retrieved.

ObjectRules Summary Table

Object rules govern the entire object.

| Rule | Value | Description | | -------------- | ----------- | ------------------------------------------------------------ | | addfields | true|false | Can new keys be added to the object | | editfields | true|false | Can values be changed in the object | | deletefields | true|false | Can keys be removed from the object | | maxupdates | number | The maximum number of updates until this object is locked to new updates. | | fields | object | Object of FieldRules |

FieldRules Summary Table

Object rules trump FieldRules in all cases. For example if an object is marked editfields = false, setting editable = true for a FieldRule will not make that field editable.

| Value | Description | | ----------- | --------------------------------------------------- | | true|false | Can this field be edited | | true|false | Can this field be deleted | | true|false | Can this field be renamed | | number | The maximum value of the field (Or length of array) | | number | The minimum value of the field |

Get An Object's Metadata

Let's say we want to get info on Joe's object:

const meta = await db.getObjectMetadata("134e366520a6f93265eb")

The output illustrates how the library stores and defines rules for the Object:

{
  "type": "meta",
  "protocol_version": "0.0.1",
  "timestamp": 1530488933194,
  "object": {
    "_id": "5b396865cbf4239c10000001",
    "name": "Joe Testerson",
    "age": 5,
    "best_friends": []
  },
  "rules": {
    "editfields": true,
    "addfields": false,
    "deletefields": false,
    "renamefields": false,
    "fields": {
      "_id": {
        "editable": false,
        "deletable": true,
        "renameable": true,
        "type": "string"
      },
      "name": {
        "editable": false,
        "deletable": true,
        "renameable": true,
        "type": "string"
      },
      "age": {
        "editable": true,
        "deletable": false,
        "renameable": true,
        "type": "number",
        "min": 0,
        "max": 100
      },
      "best_friends": {
        "editable": true,
        "deletable": false,
        "renameable": true,
        "type": "array",
        "max": 5
      }
    }
  }
}

Security & Permissions

By default objects created using this library are publicly viewable and editable. This library offers several approaches to keeping objects permissioned and secure:

AES Encryption

Objects and updates written using this library can be encrypted using AES256. Doing so results in object storage that can only be read and updated by the holder of the private encryption key.

To use AES, specify your key during initialization:

const db = new FactomObjectDB({
    //... other options
    aes_key : 'my awesome passphrase' //private key string or buffer
});

Obfuscation

The library uses deflate compression to shrink the data that is put into Factom. This means that the entries this library creates are not human readable. This will be made optional in the near future

Please note that once an object is initialized, AES and compression settings cannot be changed. Attempting to read an object using incorrect encryption or compression settings will result in an error.

HTTP API

GET

Get Object - /api/v1/db/:dbid/object/:objectid

Query Object - /api/v1/db/:dbid/object

| Query Parameter | Type | Validation | Required | | --------------- | ------ | ---------------------------------- | -------- | | query | object | JSON object, valid query structure | Y | | | | | |

Query Objects- /api/v1/db/:dbid/objects

| Query Parameter | Type | Validation | Required | | --------------- | ------ | ---------------------------------- | -------- | | query | object | JSON object, valid query structure | Y | | | | | |

POST

Commit Object- /api/v1/db/:dbid/object/:objectid

Request body must be a valid JSON object

| Query Parameter | Type | Validation | Required | | --------------- | ------ | ------------------------------- | -------- | | rules | object | JSON object, valid object rules | N | | | | | |

Commit Object Update- /api/v1/db/:dbid/object/:objectid

Testing

factom-objectdb uses chai.js

npm test

Spec

Motivation

Applications deserve easy, affordable, immutable data storage. Factom-objectdb wraps the required functionality into an easy to use package based on a universal structured data standard (JSON) and language (NodeJS), all for a fraction of the cost of competitors.

  • Cost Reduction

The price performance of immutable data solutions on Factom, like factom-objectdb, blow competitors out of the water on a $ per KB basis:

| | Cost/KB | | -------- | ------- | | Factom | $0.001 | | Ethereum | $0.13 | | NEO | $0.22 |

  • Ease Of Use

factom-objectdb does not require any knowledge of or integration with contract languages like Solidity. It is a language agnostic protocol can be implemented in any programming language. Anyone who can read JSON can understand objectdb.

  • No Exchanges or Securities

Entering data costs Entry Credits, a fixed value, non tradable token that can be purchased by anyone, anywhere. Entry credits are not securities, cost $0.001 USD each, and enable the entry of 1 KB of data permanently into the blockchain.

TODO

  • Asymmetric entry signing (Coming Soon)
  • Better examples for field and object rules
  • Full object and field rules table with descriptions
  • Signature based validation for updates
  • Make deflate compression optional for human readability

Legal

Factom-objectdb logo & Icon packs by Icons8