restlio

REST API and web application framework, built on Nodejs, Express, and Mongoose

Restlio
REST API and web application framework, built on Nodejs, Express, and Mongoose


Restlio(former app.io) is an open source REST APIand web application framework, built on Nodejs, Express, and Mongoose, which is simple, easy, quick, flexible, extendable and scalable, and which has numerous features and capabilities,
including a pre-configured server, an auto-generated admin UI and also auto-generated REST APIendpoints.

Restliois ideal for quick REST APIdevelopment.
It saves you from the complexity of API’s, and helps you to focus on your product and save time.
Moreover, it enables you to work on multiple projects within the same framework.

Why was Restlio developed?

  • In order to be used in cases, when a very quick REST APIis needed for mobile-first applications.
  • In order to answer the need for a powerful framework that will take on many tasks for you and simplify your work. It does not restrict you with given features, and it does not restrain you from writing your own code.
  • In order to provide numerous features in a single framework. For example, you can manage multiple projects. Moreover, REST APIendpoints and admin UI are automatically generated from Mongoosemodels.

What can you do with Restlio?

  • Restlioinstalls Expressmiddlewares you may need, and runs the server.
  • Restlioconnects to data sources.
  • You can use auto-generated REST APIendpoints and admin UI.
  • You can use predefined models, such as apps, users, roles, objects and actions.
  • You can use the user authentication endpoints, such as login, register, forgot password, invite and change password.
  • You can use the ACL-based user authorization.
  • You can use the social authentication.
  • You can access the auto-generated API documentation.

note:

Restliois under development, so use it at your own risk.

Table Of Contents

Getting Started

Creating an Application

The best way of using Restliois the Yeomangenerator. It generates a basic skeleton for Restliobased application. If you haven't installed Yeoman, install it first.

$ npm install -g yo

Then install the Restliogenerator.

$ npm install -g generator-restlio

Now you can generate Restlioapplication by using the Yeomangenerator.

$ yo restlio
_-----_  
    |       |    .----------------------------.  
    |--(o)--|    |   Welcome to the Restlio   |  
   `---------´   |        generator!          |  
    ( _´U`_ )    '----------------------------'  
    /___A___\  
     |  ~  |  
   __'.___.'__  
 ´   `  |° ´ Y `  

? Write app name (My App) Test App  
? Write app slug (myapp) testapp  
? Write app description (My App Description) Test App Description  

After the generator finishes installation, run the server. Don't forget to start Mongodband Redisbefore running Restlio.

$ node app

That’s all! Now Restliois up and running. Let's look at the app.js.

var Restlio = require('restlio');
new Restlio({basedir: __dirname}).run();

With these two lines you have a full featured framework, built on Express. Restliois now connected to Mongodband Redis, and is using some Expressmiddlewares you may need, such as body-parser, morgan, cors, swigas a template engine, compression, static, cookie-parser, express-sessionwith connect-redis, connect-flashand serve-favicon.

Directory Structure

Directory structure generated by Yeoman:

|--config/
|  Application configuration files. You can configurate middlewares, data source connections, roles, etc. 
|--lib/
|  Custom libraries
|--model/
|  Mongoose models
|--public/
|  Static files (css, js, images, etc.)
|--route/
|  Custom Express routes
|--view/
|  Custom view templates
|--app.js
|  Main script that starts your application
|--flightplan.js
|  Flightplan scripts
|--package.json
|  NPM package file
|--worker.js
|  Main script that starts your Kue workers

Creating an API

To create an API, you can create a Mongoosemodel, and your REST APIis ready on the fly. It's so simple! Create a file under the model directory, model/test/posts.js

module.exports = app => {

    var _query    = app.lib.query;
    var _mongoose = app.core.mongo.mongoose;
    var ObjectId  = _mongoose.Schema.Types.ObjectId;
    var Mixed     = _mongoose.Schema.Types.Mixed;

    // schema
    var Schema = {
        u  : {type: ObjectId, required: true, ref: 'System_Users', alias: 'users'},
        t  : {type: String, required: true, alias: 'title'},
        b  : {type: String, required: true, alias: 'body'},
        ca : {type: Date, default: Date.now, alias: 'created_at'}
    };

    // settings
    Schema.u.settings = {label: 'User', display: 'email'};
    Schema.t.settings = {label: 'Title'};
    Schema.b.settings = {label: 'Body'};

    // load schema
    var PostSchema = app.libpost.model.loader.mongoose(Schema, {
        Name: 'Test_Posts',
        Options: {
            singular : 'Test Post',
            plural   : 'Test Posts',
            columns  : ['users', 'title', 'body'],
            main     : 'title',
            perpage  : 25
        }
    });

    // plugins
    PostSchema.plugin(_query);

    return _mongoose.model('Test_Posts', PostSchema);

};

You have to include external models to a Restlioinstance; otherwise, Restliowon't load external sources. New app.jsis look likes that;

var Restlio = require('restlio');
new Restlio({
    basedir: __dirname,
    verbose: true,
    external: {
        model: 'test' // includes whole test directory
    }    
}).run();

Run app.jsagain;

$ node app

Yeah! Now you have a REST APIfor test.postsmodel that have sanitisation, validation, authentication, authorization, and much more features.
You also have an admin UI for this model.

Have you noticed the structure of model/test/posts.js? Restliouses express-loadunder the hood. It loads everything to the app object; thus, you can use Restlioabilities in your external files with dot notation, like this;

module.exports = app => {
    // all Restlio scripts are available in your external files
    var _mongoose = app.core.mongo.mongoose;
};

You have to use the Mongoosequery plugin, app.lib.query, to query REST APIwith several operators.
You have to pass a Mongooseschema object to app.libpost.model.loader.mongoosefunction as a parameter for additional abilities.

API Endpoints

Now you have a REST APIthat listens requests on the following endpoints:

MethodResourceDescription
GET/api/o/test.postsGet a list of objects
GET/api/o/test.posts/:idGet a single object
POST/api/o/test.postsCreate a new object
PUT/api/o/test.posts/:idUpdate an object
DELETE/api/o/test.posts/:idDelete an object

Creating an Object

Try to create an object:
Run [POST] http://127.0.0.1:3001/api/o/test.posts.

Do you see the response? You receive 403response, because Restliois ACL-ready!

{
  "meta": {
    "name": "Forbidden",
    "code": 403
  }
}

Let's allow posting an object for test.postsmodel. Go to the admin page; http://127.0.0.1:3001/admin. You can find basic auth and login cridentials in your config file; config/development.js. Choose Test Appon admin dashboard and go to the System->Actionspage from the left menu. In order to create an action for the Guestuser, click on the "+new" button. Fill in the form. Select Guestfor the Rolefield, Test Postsfor the Objectfield and Postfor the Actionfield. Try again on your HTTP client.

Do you see the response now? You received 422response, because Restliohas an API validation!

{
  "meta": {
    "name": "UnprocessableEntity",
    "code": 422,
    "message": {
      "type": "ValidationError",
      "errors": [
        {
          "path": "users",
          "message": "is missing and not optional",
          "slug": "required_error"
        },
        {
          "path": "title",
          "message": "is missing and not optional",
          "slug": "required_error"
        },
        {
          "path": "body",
          "message": "is missing and not optional",
          "slug": "required_error"
        }
      ]
    }
  }
}

Fill in the parameters and try again. Oh yeah, you received 201response now! ps: please, look at the system_users collection from Mongodb for a valid user id.

{
  "meta": {
    "name": "Created",
    "code": 201
  },
  "data": {
    "doc": {
      "_id": "576d9023420ba27f0475cd9b",
      "users": "576bca775c7a8dee2702dddb",
      "title": "title",
      "body": "body",
      "created_at": "2016-06-24T19:55:15.636Z"
    }
  }
}

It is so simple! Now you are ready to execute a query on data.

Getting Object List

In order to get a list of objects, as shown above, you must allow getting objects for the test.postsmodel. Edit previous System->Actionsrecord and add a Getpermission.
Run [GET] http://127.0.0.1:3001/api/o/test.posts;

{
  "meta": {
    "name": "OK",
    "code": 200
  },
  "data": {
    "doc": [
      {
        "_id": "576d9023420ba27f0475cd9b",
        "users": "576bca775c7a8dee2702dddb",
        "title": "title",
        "body": "body",
        "created_at": "2016-06-24T19:55:15.636Z"
      }
    ]
  }
}

You received the objects!

Query Parameters

Main query parameters for [GET] /api/o/:objectendpoints are;

ParameterQueryExample
query typeqt=find/api/o/test.model?qt=find
fieldsf=field_a,field_b/api/o/test.model?f=field_a,field_b
sorts=field_a,-field_b/api/o/test.model?s=field_a,-field_b
skipsk=10/api/o/test.model?sk=10
limitl=10/api/o/test.model?l=10
populatep=field_a,field_b/api/o/test.model?p=field_a,field_b
cache keycacheKey=test_data/api/o/test.model?cacheKey=test_data

Other query types for [GET] /api/o/:objectendpoints are; findonecountfindcountdistincttree.

Query Operators

[GET] /api/o/:objectendpoints have a number of operators;

FilterQueryExample
equalkey=a/api/o/test.model?key=a
not equalkey={ne}a/api/o/test.model?key={ne}a
greater thankey={gt}a/api/o/test.model?key={gt}a
greater than or equal tokey={gte}a/api/o/test.model?key={gte}a
less thankey={lt}a/api/o/test.model?key={lt}a
less than or equal tokey={lte}a/api/o/test.model?key={lte}a
inkey={in}a,b/api/o/test.model?key={in}a,b
not inkey={nin}a,b/api/o/test.model?key={nin}a,b
contains allkey={all}a,b/api/o/test.model?key={all}a,b
empty or not existskey={empty}/api/o/test.model?key={empty}
exists and not emptykey={!empty}/api/o/test.model?key={!empty}
exists and nullkey={null}/api/o/test.model?key={null}
nearkey={near}lon,lat,max/api/o/test.model?key={near}lon,lat,max
%like%key={:like:}a/api/o/test.model?key={:like:}a
like%key={like:}a/api/o/test.model?key={like:}a
%likekey={:like}a/api/o/test.model?key={:like}a
exists and nullkey={all}a,b/api/o/test.model?key={all}a,b
betweenkey={between}a,b/api/o/test.model?key={between}a,b

Authenticating Users

We used Guestuser on the examples above. However, we need authenticated users in real life.
You can use authentication endpoints that are ready in Restlio

Creating Client Id and Client Secret

Before using authentication endpoints, you need a Client Idand a Client Secret. All authentication endpoints require this information. Go to the admin page, http://127.0.0.1:3001/admin. You can find basic auth and login cridentials in your config file, config/development.js. Choose Test Appon admin dashboard and go to the Oauth->Clientspage from the left menu. Create a client. Fill in the Namefield, select Test Appfor the Appsfield, and fill in the Redirect Urifield (Redirect Uriis required, but is not important for now). If the Client Idand the Client Secretfields are empty, Restliowill generate these keys for you.

Authentication Endpoint Requests

Authentication endpoints require a Client Idand a Client Secret. Get the keys you generated for the Test App, and send headers as X-Client-Idand X-Client-Secret.

Registering Users

You can use [POST] /api/registerendpoint to register users. emailand passwordfields are required for the minimal configuration.

Enabling Authentication Endpoints

Before using authentication endpoints, be sure that you have enabled endpoints in the config file; otherwise, you will receive 401response.

auth: {
    'test': {
      '/api/register': true,
      ...
    }
  }

Logging in Users

You can use [POST] /api/loginendpoint to login users. Before using this endpoint, don't forget to enable it. Example response for a login request;

{
  "meta": {
    "name": "OK",
    "code": 200
  },
  "data": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NzE5OTMxMjE3NzYsInVzZXIiOnsiX2lkIjoiNTc2ZGJhMzY4YzU1NGUyOTA3N2IyMDU4In19.S1uNjX64z3aNIfEukw60bbCdQbHMOLO4Ei6tvvIc1X8",
    "expires": 1471993121776,
    "userId": "576dba368c554e29077b2058",
    "roles": [
      "test_user"
    ],
    "resources": {},
    "profile": false,
    "isEnabled": "Yes",
    "waitingStatus": "Accepted",
    "passwordChanged": "N"
  }
}

You will use data.tokenfor making authenticated requests.

Making Authenticated Requests

We used Guestuser at all examples above. Now we will try to use test.postsendpoints with a real user.
Go to the admin page, http://127.0.0.1:3001/admin, then select the System->Actionspage from the left menu. Remove the action for the Guestuser, which we had created before. Now create an action for the Userrole. Fill in the form, select Userfor the Rolefield, Test Postsfor the Objectfield, and Getand Postfor the Actionfield. We have Getand Postpermissions for the Userrole on the test.postsmodel now.
We have to send a X-Access-Tokenheader to make authenticated requests. If we don't send this header, we will receive 403response.

{
  "meta": {
    "name": "Forbidden",
    "code": 403
  }
}

Other Authentication Endpoints

Restliohas other authentication endpoints you may have need;

MethodEndpointDescription
GET/api/tokenget user data for verified token
POST/api/forgotforgot password
POST/api/reset/:tokenreset your password with forgot password token
POST/api/inviteuser invitation
POST/api/invite/:tokenaccept invitation and register with invitation token
POST/api/verify/:tokenverify user with registration token
POST/api/resendresend registration token
POST/api/change_passwordchange password
POST/api/socialsocial login or register

Next Steps

You have learned the core and the most important concepts of Restlio. However, this is yet the tip of the iceberg. Next, we will learn details about Restlio.

Routes

You know that you can use the app object and other Restlioabilities in your external sources. Adding a new route is simple.
Create a file under the route directory, route/test/posts.js. Add your route like this;

module.exports = app => {
    app.get('/my-route', (req, res, next) {
        res.json({everything: 'OK'});
    });
};

You have to include external routes to a Restlioinstance. New app.jsis look likes that;

var Restlio = require('restlio');
new Restlio({
    basedir: __dirname,
    verbose: true,
    external: {
        model: 'test',
        route: 'test'
    }    
}).run();

Run [GET] http://127.0.0.1:3001/my-route;

{
  "everything": "OK"
}

Configuring a Restlio Instance

You loaded some external sources to a Restlioinstance on the examples above. There are some other options to configure a Restlioinstance.

var Restlio = require('restlio');
new Restlio({
    basedir: __dirname,
    cores: 1,
    env: 'production',
    port: 3001,
    verbose: true,
    core: 'mongo|redis|cache',
    // boot: 'mailer|override',
    external: {
        boot: 'i18n|gitversion',
        model: 'test',
        middle: 'test',
        lib: 'test',
        route: 'test'
    }    
}).run();
  • coresYou can configure the number of Node.jsinstances to take advantage of multi-core systems. By default, a Restlioinstance uses the maximum number of cpu cores.
  • verboseIf you want to see the loaded modules, use this option.
  • envYou can set the environment with this option. You can also use process environment variable if you want; NODE_ENV=production
  • portYou can set the server's port with this option. You can also use process environment variable if you want; NODE_PORT=3001
  • coreYou can load other data sources with this option. Available options are; cache, db, elasticsearch, mongo, redis, solr.
  • bootYou can load some extra functionalities that Restliodoesn't load with minimal configuration. Available options are; mailer, mailerPool, oauthproxy, override, resize
  • externalYou can load external sources with this option. Available options are; boot, model, middle, lib, route

Views

Now you have a route file under the route directory; route/test/posts.js. Let's try to render a view in this file. Restliouses Swigas a template engine. By default, Restliois looking for the viewdirectory. You can change it from the configuration file; config/development.js.

boot: {
      view: {
          dir: 'view',
          swig: {
              cache: false
          }
      },
      ...
  }

Now our route file looks like this;

module.exports = app => {
    app.get('/my-route', (req, res, next) {
        res.render('test/my-route');
    });
};

Static Files

By default, Restliois looking for the publicdirectory to serve static files. You can change it from the configuration file; config/development.js.

boot: {
    'static': {
      dir: 'public',
      options: {
        maxAge: '1d'
      }
    },
    ...
  }

API Responses

The metakey is used to give extra information about the response. If the request is succesful and everything is ok, you will receive a 200response with data.

{
  "meta": {
    "name": "OK",
    "code": 200
  },
  "data": {
    ...
  }
}

If the data you are looking for is not found, you will receive a 404error response.

{
  "meta": {
    "name": "NotFound",
    "code": 404
  }
}

If the data you send to a resource is not valid, you will receive a 422error response.

{
  "meta": {
    "name": "UnprocessableEntity",
    "code": 422,
    "message": {
      "type": "ValidationError",
      "errors": [
        ...
      ]
    }
  }
}

If you don't have a proper permission on a resource, or if you don't send a X-Access-Tokenheader that is required by the resource, you will receive a 403error response.

{
  "meta": {
    "name": "Forbidden",
    "code": 403
  }
}

If something is wrong about any authentication endpoint, you will receive a 401error response.

{
  "meta": {
    "name": "Unauthorized",
    "code": 401,
    "message": {
      ...
    }
  }
}

If something is wrong about the server, you will receive a 500error response.

{
  "meta": {
    "name": ...,
    "code": 500,
    "message": ...
  }
}

You will receive a 201response to a POSTrequest that results in a creation.

{
  "meta": {
    "name": "Created",
    "code": 201
  },
  "data": {
    "doc": {
      ...
    }
  }
}

You will receive a 204 NoContentresponse to a successful request that won't be returning a body (like a DELETErequest).

Detailed Look at ACL

Restliohas an ACL (Access Control Lists)protection on the resources. If you don't have a proper permission on a resource, you will receive a 403error response. You can create any role you want, and select the methods you want to give access to any resources; such as, get, post, put, delete. You can use the admin UI for this process. You can create the role from System->Rolespage, and then create the action from System->Actionspage. Just fill in the form; select the Role, the Object(resource) and the Action(HTTP methods) fields.
If you want a strict control on the permissions, you can use the config file.

roles: {
    test: {
        'default': [
            {name: 'Admin', slug: 'admin'},
            {name: 'User', slug: 'user'},
            {name: 'Guest', slug: 'guest'},
            ...
        ],
        initial: {
            register: 'user'
        },
        actions: {
            user: {
                'test.posts': ['get', 'post'],
                ...
            },
            guest: {
                'test.posts': ['get'],
                ...
            }
        }
    }
}

Master User Level

Not documented

Models

Models are the core of the Restlioarchitecture. Restliobasically uses Mongoosemodels; thus, you can use all abilities of the Mongoosemodels, such as, Mongooseplugins, hooks, validations, etc.

Field Options

You can use all Mongoosefield options. Mongoosebased options are;

  • default
  • required
  • enumstring
  • lowercasestring
  • matchstring
  • maxlengthstring
  • minlengthstring
  • trimstring
  • uppercasestring
  • maxnumber, date
  • minnumber, date
  • expiresdate

The list of other Restliobased field options are;

  • aliasMongodbkey names are very important. Use the smallest keys possible, use the aliasoption when using REST API. For example;

    var Schema = {
    ...
    em : {type: String, required: true, alias: 'email', unique: true},
    ... 
    };    
  • settings

  • optional

  • allow_html

  • pattern

  • minLength

  • maxLength

  • exactLength

  • min

  • max

  • lt

  • lte

  • gt

  • gte

  • ne

  • rules

  • pair

  • owner

  • flex_ref

  • entity_acl

  • belongs_to

  • depends

  • s3

  • from

Model Loader Options

Along with those field options, there are many other loader options. The loader options add new abilities that have not been in Mongoose. You have to pass a Mongooseschema object to the app.libpost.model.loader.mongoosefunction as a parameter for these additional abilities.

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    Name: 'Test_Posts',
    ...
});

Admin UI Options

With the Optionskey you can configure admin UI options. Here are the list of the properties;

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Options: {
        singular : 'Test Post',
        plural   : 'Test Posts',
        columns  : ['users', 'title', 'body'],
        main     : 'title',
        perpage  : 25,
        ...
    },
    ...
});
  • singular
  • plural
  • columns
  • extra
  • main
  • perpage
  • sort
  • filter
  • nocreate
  • nodelete
  • noedit
  • nested
  • actions
  • analytics

Data Denormalization

Denormalizing data from another model is very simple with the Denormkey.
If the reference data you have normalized before is updated; the model loader also updates your denormalized data.
There are two ways of denormalizing the reference model data:

  • The first way is to add a seperate field to your model. Then, you can denormalize data from another field that has a reference model. For example; you can denormalize the user's email from the reference of the usersfield. In order to do this, you should add the users_emailfield to your model. Here is the structure;
var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Denorm: {
        'System_Users': {
            targets: {
                source: 'users',
                fields: {users_email: 'email'}
            }
        },
        ...
    },
    ...
});

System_Usersis the reference model of the usersfield, so our source is the usersfield.
Then we can set the fields. We want to denormalize the emaildata from the System_Usersmodel to the users_emailfield. We can set this fieldsoption like this;

fields: {users_email: 'email'}
  • The second way is to choose a reference model. Then, you can denormalize the fields of the reference model to a target field. In this way there is no source field. The model loader collects the denormalized data of every field that has the same reference model.
var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Denorm: {
        'System_Users': {
            target: 'data_users',
            fields: 'email'
        },
        ...
    },
    ...
});

Don't forget to add a field for the denormalized data. In this example, this is the data_usersfield. You have to select the Mixedtype. Write the name of the reference model to the fromoption.

d_u : {type: Mixed, alias: 'data_users', from: 'System_Users'},

Document Owner Protection

Restliohas an ACLprotection on the resources, but those are basically the permissions on the resources according to the HTTPmethods.
With this kind of protection the ownership of the document is not guaranteed. If you have a usersor a profilesfield on your model, and if you want to guarantee that the owner of the request is also the owner of the document, then you have to use the Ownerkey. Just set the users(alias: 'users') and the profiles(profile: {alias: 'profiles'}) fields and select the HTTPmethods you want to guarantee the ownership.

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Owner: {
        alias   : 'users',
        profile : {alias: 'profiles'},
        protect : {
            'get'    : true,
            'getid'  : true,
            'post'   : true,
            'put'    : true,
            'remove' : true
        }
    },
    ...
});

Masking API Data

If you are working with the REST APIs, then you will need some important features. Masking the data is one of the important features.
You may need to mask the data on a GET, a POSTor a PUTrequest. You have to use the Maskkey to mask the data. You can configure the masking options according to an HTTP method, and, according to the role or the ownership level as well.

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Mask: {
        'get': {guest: 'title,body,created_at'},
        'post': {owner: 'title,body'},
        'put': {owner: 'title,body'}
    },
    ...
});

The available levels for an HTTPmethod are; master, owner, user, guest.

Reference Counting

Sometimes you may need the count in a reference model. We have the test.postsmodel at the examples above. If you create a test.commentsmodel, and if you want to store the count of the comments in a collection on the test.postsmodel, you can use this feature. Just add a field on the test.postsmodel for the comment count. Use the CountRefkey to set the reference counting on the test.commentsmodel. Our test.commentsschema;

module.exports = app => {

    var _query    = app.lib.query;
    var _mongoose = app.core.mongo.mongoose;
    var ObjectId  = _mongoose.Schema.Types.ObjectId;
    var Mixed     = _mongoose.Schema.Types.Mixed;

    // schema
    var Schema = {
        u  : {type: ObjectId, required: true, ref: 'System_Users', alias: 'users'},
        p  : {type: ObjectId, required: true, ref: 'Test_Posts', alias: 'posts'},
        b  : {type: String, required: true, alias: 'body'},
        ca : {type: Date, default: Date.now, alias: 'created_at'}
    };

    // settings
    Schema.u.settings = {label: 'User', display: 'email'};
    Schema.p.settings = {label: 'Post', display: 'title'};
    Schema.b.settings = {label: 'Body'};

    // load schema
    var CommentSchema = app.libpost.model.loader.mongoose(Schema, {
        Name: 'Test_Comments',
        Options: {
            singular : 'Test Comment',
            plural   : 'Test Comments',
            columns  : ['users', 'posts', 'body'],
            main     : 'body',
            perpage  : 25
        },
        CountRef: {
            posts: 'comments_count'
        }
    });

    // plugins
    CommentSchema.plugin(_query);

    return _mongoose.model('Test_Comments', CommentSchema);

};

You can configure the reference counting just like this;

CountRef: {
    posts: 'comments_count'
}

If the comment is removed, then the model loader updates the count. Don't forget to add the comments_count(number) field to the test.postsmodel.

Field Reference Counting

If you want to count the size of a field that has a reference, then you can use the Countkey. It stores the count of the data in the reference collection of the source field.

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Count: {
        'source_field': 'target_field'
    },
    ...
});

Field Size Calculating

If you have an array field, and if you want to store the size of that array on the document itself, then you can use the Sizekey. Mongodbdoesn't give the size of an array by default; in order to get the array size, you have to execute an aggregation query. The Sizekey is simplifies this process. For example;

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Size: {
        tags: 'tags_count'
    },
    ...
});

If you have a tagsfield on the test.postsmodel, then simply add a new tags_countfield to your schema. The model loader calculates the size of the tagsand updates the tags_count.

Field Hook Mechanism

If you want to push the value of a field to a collection on another reference model, then you can use the Hookkey.

var PostSchema = app.libpost.model.loader.mongoose(Schema, {
    ...
    Hook: {
        push: {
            'field_of_the_source_value': 'field_of_the_target_reference:target_field',
            ...
        }
    },
    ...
});

ps: It doesn't work on the fields that are identified as entities.

Predefined Models

Restliohas a bunch of predefined models. They are used in the Restliosystem, for example user registration. You can use any predefined model you want, or use them as a reference on your models, it's up to you.

System Models

  • system.accounts
  • system.actions
  • system.apps
  • system.filters
  • system.images
  • system.invites
  • system.locations
  • system.objects
  • system.roles
  • system.users

Caching Data

If you want to cache your data on Redisfor faster response times, you can use the cacheKeyquery parameter.

Built-in Middlewares

Restliohas lots of built-in middlewares to simplify your work. Most of them are included by default. You have to enable some of the middlewares in order to use them.

Express Middlewares

  1. The REST APIpart of Restliouses these Expressmiddlewares: body-parser, morgan, cors.

  2. The Web applicationpart of Restliouses these Expressmiddlewares. swigas a template engine, compression, static, cookie-parser, express-sessionwith connect-redis, connect-flashand serve-favicon.

Restlio Middlewares

Restliohas a bunch of middlewares used internally. They are used on the resource endpoints, authentication endpoints, etc. Feel free to use them on your endpoints. You can find them in the middledirectory, and you can use a middleware like this; app.middle.acl.

Admin UI

Restliohas an admin UI, generated from the models automatically. Write your models and start to manage your data immediately. You can also manage multiple applications from the admin UI. System models are automatically filtered with the active application ID. Look at the Admin UI Optionssection for detailed options.

Built-in Job Queue

Restliohas a built-in job queue based on Kue. Restliouses it for some internal tasks, but you can easily use the job queue for your tasks.
You can get the Kueobject like this;

...
var kue = app.boot.kue; 
...

and easily create a job like this;

kue.create('task-name', {
    title: 'Task Title',
    params: {
        ...
    }
}).attempts(3).removeOnComplete(true).save();

Now look at your workers.jsfile. You have to run this file in order to start listening your job queue; $ node workers. Don't forget to include your external worker directory.

var Restlio = require('restlio');
new Restlio({
    basedir: __dirname,
    external: {
        model: 'test',
        worker: 'test'
    }
}).workers();

Create a file under the workerdirectory; worker/test/my-job.js, and write your job processor.

module.exports = app => {
    var _kue = app.boot.kue;

    _kue.process('task-name', 1, (job, done) {
        var params = job.data.params;
        ...
    });
};

Built-in Cron

Restliouses cronunder the hood for cronjobs. You can easily create a cronjob like this;

module.exports = app => {
    var _cron = app.boot.cron;

    new _cron('0 */30 * * * *', () {
        ...
    }, null, true);    
};

Built-in Mailer

Restliohas a built-in mailer based on Nodemailer. You can easily use the mailer to send your mails. You can configure your mailer from the configuration file; config/development.js.

boot: {
    ...
    mailer: {
        'test': {
            service: 'Mailgun',
            auth: {
                user: 'Mailgun user',
                pass: 'Mailgun pass'
            },
            socketTimeout: 60000
        }
    },
    ...
}

and send your mail like this;

...
var _mailer    = app.lib.mailer;
var _transport = app.boot.mailer['test'] // 'test' is your app slug.
// send your mail
new _mailer(_transport).send({
    from: ...,
    to: ..., 
    subject: ...,
    html: ...,
    ...
}); 
...

File Uploads

Not documented

On the Fly Image Resizer

Not documented

Data Synchronization

Not documented

Oauth

Not documented

API Documentation

Not documented

License

The MIT License (MIT)

Copyright (c) 2016 Selçuk Fatih Sevinç

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

HomePage

https://github.com/restlio/restlio

Repository

https://github.com/restlio/restlio.git


上一篇:timediff
下一篇:grunt-cmd-transport-xd

相关推荐

暂无相关文章

官方社区

扫码加入 JavaScript 社区