New Total.js version v2.3.0

Mon Dec 05 2016 10:42:07 GMT+0100 (Central European Standard Time), Peter Širka

New Total.js version v2.3.0

New Total.js v2.3.0 is 98% backwards compatible.

News

NoSQL embedded database

I have performed a big step to increase performance with a new great features. NoSQL embedded database can be used as a separated module $ npm install nosql (it's without dependencies). This database is a great product for small projects.

In-memory mode:

  • all documents are loaded into the memory and each change is stored on the file system
  • performance is awesome
// For the whole DB
NOSQLMEMORY('products');

// For the view only in DB
NOSQLMEMORY('blogs', 'listing');

Joins:

  • we can join documents between different databases
// One to one (each order will contain its user)
NOSQL('orders').find().make(function(builder) {
    builder.where('ispaid', true);
    builder.join('user', 'users').where('id', 'iduser').fields('name', 'email').first();
    builder.callback(function(err, response) {
        console.log(response);
    });
});

// One to many (each user will contain array of addresses)
NOSQL('users').find().make(function(builder) {
    builder.join('addresses', 'addresses').where('iduser', 'id');
    builder.callback(function(err, response) {
        console.log(response);
    });
});

Scalar operations:

  • sum, count, min, max, avg and group
  • works with joins
NOSQL('orders').scalar('sum', 'price').callback(function(err, response) {
    console.log(response);
});

// OR
NOSQL('orders').scalar('max', 'price').make(function(builder) {
    builder.year('created', 2016);
    builder.callback(function(err, response) {
        console.log(response);
    });
});

// OR with JOIN
NOSQL('users').find().make(function(builder) {
    builder.join('amount', 'orders').where('iduser', 'id').scalar('sum', 'price');
    builder.callback(function(err, response) {
        console.log(response);
    });
});

// OR group
NOSQL('users').scalar('group', 'gender').callback(function(err, response) {
    // { male: 34, female: 59 }
    console.log(response);
});

New date filters:

  • DatabaseBuilder.day(field, [operator], value)
  • DatabaseBuilder.month(field, [operator], value)
  • DatabaseBuilder.year(field, [operator], value)
NOSQL('orders').find().make(function(builder) {
    builder.year('created', 2016);
    builder.callback(function(err, response) {
        console.log(response);
    });
});

NOSQL('orders').find().make(function(builder) {
    builder.year('created', '<', 2014);
    builder.callback(function(err, response) {
        console.log(response);
    });
});

Random documents:
New version supports random feature. DatabaseBuilder.random() will return random documents.

NOSQL('products').find().take(20).random().callback(function(err, response) {
    console.log(response);
});

Updated insert/update/modify operations:

// Database inserts a new document if the document does not exist with the same `email` field
NOSQL('newsletter').upsert({ email: 'petersirka@gmail.com', created: F.datetime }).where('email', 'petersirka@gmail.com');

// Database inserts `new_model` into the DB while `update_model` won't be updated
var update_model = { ... };
var new_model = { ... };

NOSQL('products').update(update_model, new_model).where('id', update_model.id);

// Database inserts `new_model` into the DB while `modify_model` won't be modified
var modify_model = { ... };
var new_model = { ... };

NOSQL('products').modify(modify_model, new_model).where('id', modify_model.id);

NoSQL Binary:

// Browsing in all stored files
NOSQL('files').binary.all(function(err, response) {
    // e.g. [{ name: 'filename.jpg', size: 3498, type: 'image/jpeg', width: 500, height: 500, created: Date }]
    console.log(response);
});

// Removing all files
NOSQL('files').binary.clear();

NoSQL events:

var db = NOSQL('products');

// Documents
db.on('insert', function(doc) {});
db.on('update', function(doc) {});
db.on('modify', function(doc) {});
db.on('remove', function(doc) {});

// Binary
db.binary.on('insert', function(id, header) {});
db.binary.on('remove', function(id) {});
db.binary.on('clear', function() {});

// Counter
db.counter.on('hit', function(id, count) {});
db.counter.on('remove', function(id) {});
db.counter.on('clear', function() {});

Workflows

This is a new feature in this version. Workflows describes SchemaBuilder operations in a file named /workflows with the same structure as the /sitemap file. Controller contains a new schema method controller.$exec(workflow_name, callback) which executes all workflow operations in order, e.g. /workflows:

save             : workflow:'notify'    -->  save (response)   --> workflow:'notify'
save (merchant)  : workflow:'notify'    -->  save              --> workflow:'notify'     --> workflow:'bill' (response)

Controlller:

exports.install = function() {
    // Performs "save" workflow automatically
    // Output: "json"
    F.route('/api/users/create/',   ['*User --> save', 'post']);
    F.route('/api/clients/create/', ['*Client --> save', 'post']);    

    // Output: "view" with a model
    F.route('/api/merchant/create/', 'success', ['*Merchant --> save', 'post']);

    // Output: user defined
    F.route('/api/merchant/create/', json_customer_create, ['*Customer', 'post']);
};

function json_customer_create() {
    var self = this;
    self.$exec('save', function(err, response) {
        self.json(err ? err : response);
    });
}

IMPORTANT: (response) keyword means that controller.$exec() returns only the one result from this operation. Otherwise returns array of results from operations.

New SchemaBuilder types

NEWSCHEMA('Product').make(function(schema) {

    // ENUM:
    // A value of size has to be according the array below (works with numbers too):
    schema.define('size', ['XS', 'S', 'M', 'L', 'XL', 'XXL']);

    // KEY & VALUE
    // A value can contain "billing" or "postal" value
    schema.define('address', { billing: 'Billing address', postal: 'Postal address' });

});

Describing SchemaBuilder operations

schema.addWorkflow('check', function(error, model, options, callback) {
    // ... user-defined code ...
}, 'Workflow checks whether user exists or not.');

schema.addTransform('xml', function(error, model, options, callback) {
    // ... user-defined code ...
}, 'Transformation transforms the model to XML.');

schema.setSave(function(error, model, options, callback) {
    // ... user-defined code ...
}, 'Saving user data into the DB');

How to get all schema descriptions?

// Prints all descriptions in the schema
console.log(schema.meta);

// Prints description of transformation "xml"
console.log(schema.meta['transform#xml']);

// Prints description of workflow "check"
console.log(schema.meta['workflow#check']);

// Prints description of "save"
console.log(schema.meta['save']);

Added a new argument in all SchemaBuilder operations

  • controller argument is filled when an operation is executed from a controller
schema.setSave(function(error, model, options, callback, controller) {
    // custom code
});

schema.setQuery(function(error, options, callback, controller) {
    // custom code
});

schema.addWorkflow('check', function(error, options, callback, controller) {
    // custom code
});

Scripting

This new feature is really great solution for user-defined scripts because a scope of the script is secured (require and global variables/aliases are not accessible with except RESTBuilder). It's an experiment and more info in Total.js documentation. This solution doesn't use Node.js vm.

SCRIPT('next(value + 10)', 10, function(err, response) {
    console.log(response); // 20
});

SCRIPT('value.name = value.name.toLowerCase(); next(value);', { name: 'PETER' }, function(err, response) {
    console.log(response); // { name: 'peter' }
});

Data validators

You can change built-in Regular Expression validators easily. These validators use Total.js Schemas.

F.validators.email = /your-regexp/;
F.validators.phone = /your-regexp/;
F.validators.zip = /your-regexp/;
F.validators.url = /your-regexp/;

View Engine

  • supports @{continue} and @{break} commands in loops
  • updated compilation of dynamic views to new methods:
// In a controller:
controller.viewCompile('Hello @{model.title}', { title: 'World!' });

// In-line:
var output = F.viewCompile('Hello @{model.title}', { title: 'World!' });

// Or in views
// @{viewCompile('Hello @{model.title}', model);

Common

  • Controller is a global variable, so it's easy to extend its prototype
  • F.kill([signal]) is a new method for killing instance of Total.js
  • HttpFile.rename(filename, [callback(err)]) performs rename operation for an uploaded file

Support Total.js on GitHub and follow us on Twitter: @totalframework. We have prepared another updates, so stay tuned for more.


Tags

Follow us

Latest blogs
Flow v6 is here!
Thu Mar 07 2019 11:53:54 GMT+0100 (Central European Standard Time)
A critical security fix
Wed Feb 13 2019 22:15:39 GMT+0100 (Central European Standard Time)
New release: Total.js v3.2
Wed Feb 13 2019 22:14:39 GMT+0100 (Central European Standard Time)
Total.js Wiki v2
Fri Jan 04 2019 22:15:01 GMT+0100 (Central European Standard Time)
Total Year 2018
Thu Jan 03 2019 21:14:00 GMT+0100 (Central European Standard Time)

Latest comments
Nice tip
Mauro Junior
Thu Sep 20 2018 21:41:02 GMT+0200 (Central European Summer Time)
Not only for Total.js. You can communicate with different websocket servers.
Peter Širka
Mon Apr 23 2018 20:08:20 GMT+0200 (Central European Summer Time)
Marko: you need to create a buffer with this codepage and write byte-to-byte string. I recommend ...
Peter Širka
Mon Apr 23 2018 20:06:21 GMT+0200 (Central European Summer Time)
Is WEBSOCKETCLIENT only for internal ws connections between totaljs apps?
Stelios Stephanua
Fri Mar 16 2018 06:04:22 GMT+0100 (Central European Standard Time)
Total.js is amazing! ;)
Leonardo Hessel
Tue Dec 19 2017 19:51:15 GMT+0100 (Central European Standard Time)

Pixabay


Read more

Flow v6 is here!

News: We have released a new version of Flow. This version brings great new features and UI improvements.

Thu Mar 07 2019 11:53:54 GMT+0100 (Central European Standard Time)
A critical security fix

News: We were notified about the critical security bug in Total.js framework. Read a prevention.

Wed Feb 13 2019 22:15:39 GMT+0100 (Central European Standard Time)
New release: Total.js v3.2

News: This new release brings a critical security fix and small new improvements. Update Total.js now.

Wed Feb 13 2019 22:14:39 GMT+0100 (Central European Standard Time)
Total.js Wiki v2

Products: I have released a new version of Total.js Wiki. New version brings new improvements.

Fri Jan 04 2019 22:15:01 GMT+0100 (Central European Standard Time)
Total Year 2018

Business: Last year was perfect for Total.js platform. Total.js platform grows up and it has great results.

Thu Jan 03 2019 21:14:00 GMT+0100 (Central European Standard Time)
Total.js Code Editor v1

Products: Try our real-time collaboration tool for Total Developers. Code Editor offers great features for development.

Fri Dec 07 2018 22:55:13 GMT+0100 (Central European Standard Time)