Construire une ressource REST complète avec des actions
Une ressource REST se compose de six opérations : liste (query), read, insert, update (remplacer), patch (modifier quelques champs) et remove. Dans Total.js, chacune est une action avec sa propre validation, de sorte que la table des routes reste une simple correspondance entre URL et action. params valide l'identifiant de l'URL, query les filtres de la liste, input le corps. Dans une action, $.params, $.query et le corps validé (deuxième argument de action) sont déjà des valeurs propres.
Signalez un enregistrement manquant avec $.invalid(404) : il répond avec le code de statut et une erreur JSON, de la même façon pour chaque action. $.success() répond { "success": true } et $.callback(value) répond avec une valeur, qui est en outre filtrée par le output de l'action. UID() crée l'identifiant d'un nouvel enregistrement.
patch a besoin de partial: true. Sans cela, un champ qui n'a pas été envoyé est tout de même rempli avec la valeur par défaut de son type ('' pour un String), et update() écraserait la valeur enregistrée par ce texte vide. Avec partial: true, seuls les champs présents dans la requête atteignent l'action.
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');
};