Pillarsjs & GoblinDB

 Prototype like a Boss!

Ulises Gascón

Full Stack developer and proud co-founder of Open Source Weekends (OSW)

 

Open Source Ecosystem active collaborator

 

Tech Freelance consultant & Instructor at Fictizia

  • JavaScript
  • Nodejs
  • Pillarsjs
  • GoblinDB
  • Questions!

OSWeekends

A truly open source community

What is OSW?

We meet once per month to create and contribute to open source.

Our aim for the community meetings is to share knowledge and allow the

ideas to flow.

Everybody is welcome. The only requeriment is to do ethical , non-profit Open Source project.

OSWaldito

Code and Design: Github | License: GNU GPL v3

OSW in numbers

Meetup members:

Slack people:

Sponsors:

+1500

+380

10

Community projects:

Collaborative projects:

+20

+10

Slack messages:

+172k

 

JavaScript (/ˈdʒɑːvəˌskrɪpt/), often abbreviated as JS, is a high-level, dynamic, weakly typed, prototype-based, multi-paradigm, and interpreted programming language.

 

Each of the many JavaScript engines represent a different implementation of JavaScript, all based on the ECMAScript specification, with some engines not supporting the spec fully, and with many engines supporting additional features beyond ECMA.

 

As a multi-paradigm language, JavaScript supports event-driven, functional, and imperative (including object-oriented and prototype-based) programming styles.

  • Asynchronous I/O (Speed)
  • Real time Web applications
  • Present Everywhere (JavaScript)
  • Solves All Database Queries
  • Data streaming
  • Increases productivity
  • Community Friendly (NPM)
  • Not just for HTTP
  • Code Shifting
  • Used for Hosting
  • High performance
  • Easy modification

Why? Just a hipster thing?

The Traditional Model

The Traditional Model

result = db.executeQuery("SELECT name FROM Customers WHERE id=1001");

// Wait for result

// Do something with result

The Node.js Model

The Node.js Model

db.executeQuery("SELECT name FROM Customers WHERE id=1", function(result, error){
        // Do something with the result
    });

Nodejs vs. PHP

Built-in Modules

  • assert Provides a set of assertion tests
  • buffer To handle binary data
  • child_process To run a child process
  • cluster To split a single Node process into multiple processes
  • crypto To handle OpenSSL cryptographic functions
  • events To handle events
  • fs To handle the file system
  • http To make Node.js act as an HTTP server
  • https To make Node.js act as an HTTPS server.
  • net To create servers and clients
  • os Provides information about the operation system
  • path To handle file paths
  • stream To handle streaming data
  • and more....

The Node.js Ecosystem

State of the Union 2016 @NPM

23 humans work @NPM

In the las 28 days, npm users have installed 18 million packages

In the las 28 days, npm users have download 6 billion packages

66% of installs are from cache!

39,692 packages publishes/week

39,692 packages publishes/week

4,682 new packages last week

State of the Union 2016 @NPM

160 people publish their first package every week

102,460 publishers

314,582 registered users

You can only unpublish your package within 24 hours

You can dissociate and deprecate

The registry is immutable

The registry is fast

The registry is 75% faster than Git

Top Relevant packages

Quick Demo

const project = require('pillars'); 

project.services.get('http').start(); 

// Server POO Oriented:					
project.routes.add(new Route({
    method: ["GET","POST"], 
    port: 8080,
    path: "/hola",
    https: false,
    cors: true,	
    session: true 
  },function(gw){
    gw.session.counter = gw.session.counter || 0;
    gw.session.counter++;
    gw.html("Hi!!, Your IP: " + gw.ip + " and you are the visitor nbr "+ gw.session.counter);
});

Features

  • Support to Express.js ecosystem
  • Creators are available in OSW Slack
  • Open Source (MIT License)
  • Dynamic configuration & routes
  • Gangway object (req + res)
  • Heritage in routes
  • Easy & Fast to learn

Feature: Dynamic Router

project.routes.add(new Route({
    method: "GET",
    path: "/get"
  },function(gw){
    gw.send("Hello, I only accept requests with the GET method");
}));

project.routes.add(new Route({
    method: ["GET","POST"],
    path: "/getpost"
  },function(gw){
    gw.send("Hello, I accept requests with the GET and POST method");
}));

project.routes.add(new Route({
    id:"switch",
    path: "/switch"
  },function(gw){
    let routeFocus = project.routes.get("get");
    routeFocus.active = !routeFocus.active;
    gw.send("Now the route 'get' is: "+ routeFocus);
}));

Feature: Gangway

const myRoute = new Route(function(gw){

  const POST = gw.content.params; 
  const GET = gw.query;
  const cookie = gw.cookie;
  const userAgent = gw.ua;
  /*
  ua:{ 
    mobile: false,
    os: 'Windows NT 6.1; WOW64',
    engine: 'Blink',
    browser: 'Chrome'
  }
  */
  const id = gw.id; 			// Request ID
  const ip = gw.ip;			// Client's IP
  const browserLang = gw.language;	// Browser language 
  const cors = gw.cors; 		// CORS Management. 
  const method = gw.method;		// Method used					
  const encoding = gw.encoding;         // encoding
  gw.json(gw);                          // Return a JSON to the client
});

Feature: Middelware


const project = require('pillars'); 

project.services.get('http').start(); 

// Server POO Oriented:					
project.routes.add(new Route({
    method: ["GET","POST"], 
    port: 8080,
    path: "/hola",
    https: false,
    cors: true,	
    session: true 
  },function(gw){
    gw.session.counter = gw.session.counter || 0;
    gw.session.counter++;
    gw.html("Hi!!, Your IP: " + gw.ip + " and you are the visitor nbr "+ gw.session.counter);
});

project.middleware.add( 
  new Middleware({ 
      id: "idMiddleware"
    },function(gw, next){
      console.log("Hello from the other side, I'm a middleware");
      next();
}));

Feature: Services

const project = require('pillars');

// http services
project.services.add((new HttpService({
  id:'http2',
  port: 3003
})).start());

// https service
const fs = require('fs');
project.services.add((new HttpService({
  id:'https',
  key: fs.readFileSync('./localhost.key'),
  cert: fs.readFileSync('./localhost.crt'),
  port: 3001
})).start());

//...

project.services.get('http2');
project.services.get('https');

Ecosystem

  • JSON.crypt Encrypt/Decrypt manager for JS objects in Node.js: JSON.crypt(object)
  • Modelator Data deep modeling for Node & Pillars
  • Templated Multi template engine manager for Node.js
  • ObjectArray JS ObjectArray Class, .search('id') .move('id','to') .remove('id') etc...
  • Scheduled Scheduled job manager for JavaScript, linux cron pattern.
  • Textualization Internationalization (i18n) for Node.js => i18n('path.to.mi.text',{...params...},lang);
  • JSON.decycled Decycled versión for JSON.stringify, resolve circulars and more. Reverse by JSON.revive().

Ecosystem

  • Pillars.status Pillars status panel, all relevant information about your project in one place
  • String.format String prototype method -> "Hello {name}!".format({name:"Homer"});
  • Procedure Simple JS async development, What promise?
  • Jailer Simple key checking methodology.

  • Date.format JS Date format => date.format("Today {Y}/{M}/{D} at {h}:{m}:{s}h and {ms}ms");

  • Crier Log dispatcher , multi store, tree grouping, formatter, meta handling, error handling.

  • Eventium Async event manager for Node.js Objects

In production

  • Oswaldito. OSWeekends Robotic cofounder. It manages Slack, hangouts and Twitter...
  • Pillarsjs Documentation. The Official documentation was made in Pillarsjs and hosted by the core team.
  • Aire Madrid. An Open Source web applitacion that shows Air Quality in Madrid.
  • AireMAD. An amazing open source webapp that shows you info about Weather, pollution, noise, flu...
  • Curratelo.es. An Experimental job portal with realtime jobs offers from twitter and weekly info about github, domestika, etc... offers

Goblin Philosophy

Goblin Philosophy

Quick Demo

+

Add it to your project

Install the package
Add it to your project
npm install goblindb --save
var GDB = require("goblindb");

var goblinDB = GDB();

// Your code...

Saving Data

You have many options to save data. As Goblin is a key/value database you need to know what is the key that you want to use/create.

  • set(key, data). Write or replace data to a defined key (optional)
  • push(data). Write data in a new key (random name added, like MewhnDIutVhm3hulgTaAJj6Utb47GOwe)
  • update(data, key). Add and modify data to a defined key

Saving Data

set(key, data). Write or replace data to a defined key (optional)

var GDB = require("goblindb");

var goblinDB = GDB();

// set data in db.admin
goblinDB.set({"name": "Ulises", "role": "developer"}, "admin");

// set data in root
goblinDB.set({"hello": "Human...!"});

Saving Data

push(data). Write data in a new key (random name added, like MewhnDIutVhm3hulgTaAJj6Utb47GOwe)

var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.push({"name": "Ulises", "role": "developer"})
goblinDB.push(["other-data", true, 123])

console.log(goblinDB.get());
/* Console:
{ MewhnDIutVhm3hulgTaAJj6Utb47GOwe: { name: 'Ulises', role: 'developer' },
  j3zKjX7WpdTDpRPNVWGE1jPMHEtUPWq6: [ 'other-data', true, 123 ] }
*/

Saving Data

update(data, key). Add and modify data to a defined key

var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.update({"name": "CodingCarlos", "friends": ["Ulises", "Jose"]}, "admin");

Retrieving Data

By default Goblin will create an empty json file as database storage, if the file exist it will added to Goblin.

Return data from a key or the whole DB
var GDB = require("goblindb");

var goblinDB = GDB();

console.log(goblinDB.get())
// {"hello":"world!","array":["aaaa",true,5],"objectData":{"property": 1}}

console.log(goblinDB.get("hello"))
// {"hello":"world!"}
goblin_bd.json
{"hello":"world!","array":["aaaa",true,5],"objectData":{"property": 1}}

Fun with Events

The event will return an object that contains previous data and current data. At the moment the the listeners can be added only to the database root

You can specify the trigger event:

  • add
  • update
  • delete
  • reconfigure
  • change (always it will be triggered)

You can use events in order to react to changes in the database. All the events are managed internally by Goblin inside as hooks.

Fun with Events

var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.on('change', function(changes){
    console.log("cambio:", changes)
    console.log("====================")
});

// more code...

goblinDB.off('change', function(changes){
    console.log("cambio:", changes)
    console.log("====================")
});
  • on() Add a new function to be triggered on a specific change.
  • off() Remove a previous record event

Ambush Functions

You can store also anonymous functions in GoblinDB, we call this functions Ambush.

 

Once you add Ambush functions to GoblinDB... the system will save them under a .goblin file.

 

This feature will allow you to bring your functions together with your data to a new projects.

Ambush Functions

You can perform few basic operations to ambush functions through Goblin specific methods (similar to data ones...).  

  • add()
  • update()
  • remove()
  • run()
  • details()
  • list()

Ambush Functions

All the ambush functions has an specific setup. Internally they are objects with specific methods and properties

  • id, this reference must be unique and also a string.
  • description, this will add additional information about the current ambush function (opt & string)
  • category, this array will help us to filter our ambush functions.
  • action, this is the key feature. This method can be executed from GoblinDB on demand. Only two optional parameters are acepted: arguments (no specific data type) and callback (function).

Ambush Functions

Add a simple ambush function.
var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.ambush.add({
	id: "simple-function",
	category: ["documentation"],
	description: "This is a simple function",
	action: function(){
		console.log("Hello World");
	}
});

goblinDB.ambush.run("simple-function"); //Console -> Hello World

Ambush Functions

Add a simple ambush function with arguments.
var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.ambush.add({
	id: "argument-function",
	category: ["documentation"],
	description: "This is an ambush function with arguments",
	action: function(argument){
		console.log("Hello", argument);
	}
});

goblinDB.ambush.run("argument-function", "World"); //Console -> Hello World

Note: Only one argument can be provided by run method. In case that you need more than one argument, please use an array or an object.

Ambush Functions

Add an ambush function with arguments and callback
var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.ambush.add({
	id: "callback-function",
	category: ["documentation"],
	description: "This is an ambush function with arguments and callback",
	action: function(argument cb){
		cb("Hello " + argument);
	}
});

goblinDB.ambush.run("callback-function", "World", function(data){
	console.log("The Callback data:", data);
}); //Console -> The Callback data: Hello World

Ambush Functions

Remove an ambush function
var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.ambush.add({
	id: "simple-function",
	category: ["documentation"],
	description: "This is a simple function",
	action: function(){
		console.log("Hello World");
	}
});

goblinDB.ambush.remove("simple-function");

Ambush Functions

Update an ambush function
var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.ambush.add({
	id: "simple-function",
	category: ["documentation"],
	description: "This is a simple function",
	action: function(){
		console.log("Hello World");
	}
});

goblinDB.ambush.update("simple-function", {"category": ["updated-documentation"]});

Ambush Functions

Get the details about an ambush function
var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.ambush.add({
	id: "simple-function",
	category: ["documentation"],
	description: "This is a simple function",
	action: function(){
		console.log("Hello World");
	}
});

var copy = goblinDB.ambush.details("simple-function");
copy.action() //Console -> Hello World

Ambush Functions

Get a list of all the ambush function available in the database.
var GDB = require("goblindb");

var goblinDB = GDB();

console.log("All the Ambush functions:", goblinDB.ambush.details());
console.log("Now related to documentation:", goblinDB.ambush.details("documentation"));

Note: You can filter by categories too.

Extra Features

getConfig() & updateConfig() modify/replace/extend configuration.

var GDB = require("goblindb");

var goblinDB = GDB();

console.log(goblinDB.getConfig())
// { logPrefix: '[GoblinDB]', file: './goblin_bd.json', recordChanges: true }

goblinDB.updateConfig({ logPrefix: '[GoblinDB-modify]'})

console.log(goblinDB.getConfig())
// { logPrefix: '[GoblinDB-modify]', file: './goblin_bd.json', recordChanges: true }

Extra Features

stopStorage() & startStorage() enable/disable the storage in disk.

 

var GDB = require("goblindb");

var goblinDB = GDB();

goblinDB.stopStorage();

// more code that will not touch be stored in the disk...

goblinDB.startStorage();
// Now the current GoblinDB will be stored in disk and it will keep doing it

Roadmap

  •  Support multidimensional navigation in the database 
  •  Support to chain methods.
  •  Plugin documentation example
  •  Add basic query methods as a plugin.
  •  Add advance query methods as a plugin.
  •  Add support to .once() method for events.
  •  Additional events to support (config changes, etc...).
  •  Add additional support to Backup Goblin with other databases like Firebase, Mongo... in real time as a plugin.
  •  Full documentation in JSDoc.
  •  Gulp Tasks Improvement.
  •  Test support for Events using Sinon.
  •  Test refactor in order to separate more the test cases.

Contribute

Demo Time

QUESTIONS

¡Thank U!

Dreams are extremely important. You can't do it unless you imagine it.  

- George Lucas

Pillarjs & GoblinDB, Prototype like a Boss!

By Ulises Gascon Gonzalez

Pillarjs & GoblinDB, Prototype like a Boss!

Pillarjs & GoblinDB, Prototype like a Boss! | DevFest Coimbra 2017

  • 1,617