Teljes REST-erőforrás építése akciókkal
Egy REST-erőforrás hat műveletből áll: lista (query), read, insert, update (csere), patch (néhány mező módosítása) és remove. A Total.js-ben mindegyik egy saját validálású akció, így az útvonaltábla egyszerű URL–akció megfeleltetés marad. A params az URL azonosítóját, a query a lista szűrőit, az input a törzset validálja. Egy akción belül a $.params, a $.query és a validált törzs (az action második argumentuma) már tiszta értékek.
A hiányzó rekordot a $.invalid(404) jelzi: az állapotkóddal és egy JSON-hibával válaszol, minden akciónál ugyanúgy. A $.success() a { "success": true } értékkel válaszol, a $.callback(value) pedig egy értékkel, amelyet ráadásul az akció output-ja is szűr. A UID() az új rekord azonosítóját hozza létre.
A patch-hez partial: true kell. Enélkül egy el nem küldött mezőt is feltölt a típusa alapértéke (String esetén ''), és az update() a tárolt értéket ezzel az üres szöveggel írná felül. A partial: true esetén csak a kérésben szereplő mezők jutnak el az akcióhoz.
NEWACTION('Products/query', {
name: 'List products',
query: 'page:Number, search:String',
output: 'items:[id:UID, name:String, price:Number], page:Number',
action: function($) {
var page = $.query.page || 1;
var builder = NOSQL('products').find().sort('name').take(10).skip((page - 1) * 10);
if ($.query.search)
builder.search('name', $.query.search);
builder.callback((err, items) => $.callback({ items: items, page: page }));
}
});
NEWACTION('Products/read', {
name: 'Read a product',
params: '*id:UID',
output: 'id:UID, name:String, price:Number',
action: function($) {
NOSQL('products').read().where('id', $.params.id).callback(function(err, item) {
if (item)
$.callback(item);
else
$.invalid(404);
});
}
});
NEWACTION('Products/insert', {
name: 'Create a product',
input: '*name:String, *price:Number',
action: function($, model) {
model.id = UID();
NOSQL('products').insert(model).callback(() => $.callback({ id: model.id }));
}
});
NEWACTION('Products/update', {
name: 'Replace a product',
params: '*id:UID',
input: '*name:String, *price:Number',
action: function($, model) {
NOSQL('products').update(model).where('id', $.params.id).callback(function(err, count) {
if (count)
$.success();
else
$.invalid(404);
});
}
});
NEWACTION('Products/patch', {
name: 'Change some fields of a product',
partial: true,
params: '*id:UID',
input: 'name:String, price:Number',
action: function($, model) {
NOSQL('products').update(model).where('id', $.params.id).callback(function(err, count) {
if (count)
$.success();
else
$.invalid(404);
});
}
});
NEWACTION('Products/remove', {
name: 'Remove a product',
params: '*id:UID',
action: function($) {
NOSQL('products').remove().where('id', $.params.id).callback(function(err, count) {
if (count)
$.success();
else
$.invalid(404);
});
}
});exports.install = function() {
ROUTE('GET /products/ --> *Products/query');
ROUTE('GET /products/{id}/ --> *Products/read');
ROUTE('POST /products/ --> *Products/insert');
ROUTE('PUT /products/{id}/ --> *Products/update');
ROUTE('PATCH /products/{id}/ --> *Products/patch');
ROUTE('DELETE /products/{id}/ --> *Products/remove');
};