create with basyt
because simple is beautiful
Tell Me More

What is basyt?

basyt is a minimalist package to create JSON API server.

Typical scenario to use basyt is when you need to serve a rest-like JSON API that provides create/read/update/delete/query actions for your data entities.

In basyt, you simply declare entities. Then basyt does the rest for you. If you need authentication or custom actions related to your entity, you can easily decorate your entity.

You can connect your database using basyt collections and seamlessly integrate with your AngularJS web application using basyt angular module.

basyt is an extension over awesome web framework expressjs. By composition of basic middlewares, basyt simplifies building JSON API server over express.

Features

simple ∴ beautiful

Builtin API Methods

basyt provides builtin methods for creating, reading, updating, deleting, listing and querying declared entities. These methods can be extended by hook definitions.

Authentication

basyt provides json web token based authentication. You can easily use inside your mobile applications. You do not need to manage sessions, there will not be cookies, hence no CSRF trouble.

Authorization

basyt provides role based access control. You can easily define authorization levels for creating, updating, deleting, querying and reading for each entity.

Entity Models

basyt provides flexible entity definition capability. You can easily add extra custom actions, define hooks for database operations of entities.

Database Connections

basyt provides generic collection interface. MongoDB collection interface is implemented, and elasticsearch is planned for the next step.

Notification Ready

basyt provides socket.io based websocket integration and emits entity update events in Redis to be consumed for notification implementation.

Quick Start

To utilize basyt as foundation of your API, you need several declarations. Firstly basyt needs global APP_CONFIG object.

GLOBAL.APP_CONFIG = {
    base_folder: __dirname + '/', 
    //base_folder definition is required, you probably will keep this line as it is

    package_file: GLOBAL.APP_CONFIG.base_folder + 'package.json', 
    //path for package.json file. basyt uses package.json to get application name and version.
    //when not defined package_file is set to base_folder + 'package.json'

    basyt: { //scope for basyt related configuration
        port: 5850, 
        //port number that basyt HTTP server will listen
        entity_path: '/',
        //url base path for entity API endpoints. default is '/'
        //if it is set to 'foo' then base address for entity is http://hostname/foo/entity
        entities_folder: GLOBAL.APP_CONFIG.base_folder + 'entities',
        //path for folder that contains entity definitions.
        //when not defined, entities_folder is set to base_folder + 'entities'
        controllers_folder: GLOBAL.APP_CONFIG.base_folder + 'controllers',
        //path for folder that contains entity-free controller definitions.
        //when not defined, controllers_folder is set to base_folder + 'controllers'
        enable_ws: true,
        //enables socket.io based websocket. default true
        enable_cors: true, 
        //enables CORS setup. default false
        enable_auth: true,
        //enables user management and authentication. default true
        cors: { 
          //CORS headers to be setup. Required only when enable_cors is true
          //following values can be set for CORS setup.
          //Content_Type header field is allowed by default
          //Authorization header is allowed when auth is enabled
            origin: 'http://localhost:8580',
            methods: 'GET,PUT,POST,DELETE',
            headers: ['accept']
        },
        auth: {
          //required when enable_auth is true.
            token: 'your.secret.token',
            //token to be used for jwt
            method: 'jwt'
            //currently only supported method is jwt
        }
        disable_discovery: false, 
        //when discovery is enabled, GET request to server's base address will provide all possible API
    },
    mongodb: { //scope for mongodb collection configuration
        connection: 'mongodb://localhost/basyt_db'
    }
};

after declaring global APP_CONFIG, you simply instantiate basyt

var basyt = require('basyt');
var basytApp = basyt();

basyt explores entities and controllers in corresponding folders and generates API endpoints. In entities folder, entity declarations are like in the following example

module.exports = {
    collection: { //collection is database aspect of entity
        storage: "mongodb",
        //currently the only storage option is mongodb. it is used to select collection
        name: "test_entity",
        //name of entity, used for url path and as collection name
        strict: true,
        //when collection is NOT strict, it accepts attributes that are not defined in attributes list
        attributes: { //list of the attributes of entity
            //following attributes are given as example
            name: {type: "string", required: true},
            email: "email",
            url: "url",
            telephone: {
                type: "numeric",
                minLength: 7,
                maxLength: 11
            }
        },
        event_names: [':test_entity'],
        //basyt emits redis event for entity updates. 
        //By default, it emits entity:: event
        //for additional events event_names list is used.
        methods: {
          //list of collection methods
          //here hook functions for entity can be defined. for instance beforeCreate, afterCreate etc.
          //see basyt-base-collection/index.js hook functions for complete hook functions and their
          //signature
        }
    },
    auth_levels: {
      //authentication levels for API actions for entity. Default authentication level is 'USER'
      'read': 'USER',
      'list': 'USER',
      'update': 'USER',
      'update_bulk': 'USER',
      'query': 'USER',
      'create': 'USER',
      'create_bulk': 'USER',
      'delete': 'USER',
      'delete_bulk': 'USER'
    },
    //you can disable/enable any API action for entity.
    disable_read: false,
    disable_list: false,
    disable_update: false,
    disable_delete_bulk: true,
    disable_create_bulk: true,
    disable_update_bulk: true,
    customActions: {
      //here you can define any other actions for the entity
      test: {
        path: '/:entity_id/test',
        //url path that action will bind to
        method: 'put',
        //HTTP method for the action
        auth_level: 'ADMIN',
        //Authentication level for the action
        action: function custom_action(req, res) {
          //action function
          return res.json({success: true});
        }
      }
    }
};

In controllers folder, entity-free controllers are declared. Those controller files include definitions similar to customActions field of entity declarations.

module.exports = {
  example_action: {
  path: '/example_action',
  //url path that action will bind to
  method: 'GET',
  //HTTP method for the action
  auth_level: 'USER',
  //Authentication level for the action
  action: function example_action(req, res) {
    //action function
    return res.json({success: true});
  }
}
};

For a controller file named test_controller.js with content given above, there will be an api for address http://hostname/test_controller /example_action.

Components

basyt

Main package for JSON API Server
Available in npm
npm install basyt

basyt-mongodb-collection

Database connection package for MongoDB
Available in npm
npm install basyt-mongodb-collection

basyt-angular

AngularJS module for basyt servers
Available in bower
bower install basyt-angular

basyt-elasticsearch-collection

Elasticsearch datastore connection

Coming Soon

basyt-redis-collection

Redis datastore connection

Coming Soon

About

OK, what is basyt then?

It is a package of patterns that extends capabilities of expressjs that will make you develop your API server quicker.

Is it a nodejs web framework?

Nope, it is not. It actually tries hard not to be a framework. Being a framework and providing simplicity contradicts, and basyt prefers to be in the simplicity side.

Do I really need basyt?

Well, if you have more than a few entities, you do not want to repeat yourself while writing database operations, validations and authorization services, then it may be.

But if you have more simple API needs, do not bother using any additional packages, expressjs itself is probably more than enough for you

And the name means?

In Turkish basit means simple. That is the motivation: an extension over expressjs to make things simpler. Since our company's initials are YT, we decided to call the project basyt, simple web package from Yonca Teknoloji.