[go: nahoru, domu]

corbel-composer

0.0.9 • Public • Published

corbel composer

Build Status npm version Dependency status Dev Dependency Status Coverage Status

A corbel-composer is a middleware based in nodeJS with express, to offer developers to make his own specific application API bsed in corbel-js

Homepage

Overview

[text]

Diagram

[image]

QuickStart

  • install

    npm install -g bq/corbel-composer
    
  • run server

    corbel-composer
    

Postman Playground

  1. Get postman
  2. Import corbel-composer collection:
https://raw.githubusercontent.com/bq/corbel-composer/master/doc/postman/postman.json
  1. Import evironment example:
https://raw.githubusercontent.com/bq/corbel-composer/master/doc/postman/environment.example.json
  1. Import globals:
https://raw.githubusercontent.com/bq/corbel-composer/master/doc/postman/globals.example.json
  1. Enjoy!

Phrase Model

{
    "url": "phraseName",
    "get": {
        "code": "res.render('index', {title: 'hello world'});",
        "doc": {
            "description": "Phrase description",
            "queryParameters": {
                "param1": {
                    "type": "number",
                    "description": "Param description",
                    "default": 0
                }
            },
            "responses": {
                "200": {
                    "body": {
                        "application/json": {
                            "schema": "{\n\t"$schema": "http://json-schema.org/schema",\n\t"type": "object",\n\t"description": "A canonical song",\n\t"properties": {\n\t\t"title": {\n\t\t\t"type": "String"\n\t\t},\n\t\t"artist": {\n\t\t\t"type": "String"\n\t\t}\n\t},\n\t"required": ["title", "artist"]\n}"
                        }
                    }
                }
            }
        }
    }
}

Example Phrases

count value in collections query

{
    "url": "countExample",
    "get": {
        "code": "CORBEL-JS_SNIPPET"
    }
}

where code should be a string with this corbel-js snippet:

var count;
corbelDriver.resources.collection('test:ComposrTest').get(undefined, {
    aggregation: {
        $count: '*'
    }
}).then(function(response) {
    count = response.data.count;
    return corbelDriver.resources.collection('test:ComposrTest').get();
}).then(function(response) {
    res.send({
        data: response.data,
        'count': count
    });
}).catch(function(error) {
    res.send(error);
});

Path & query parameters

{
    "url": "paramsExample/:pathparam",
    "get": {
        "code": "res.status(200).send('path param: ' + req.params.pathparam + ',  query param: ' + req.query.queryparam);"
    }
}

Reference

API design best practices

Naming

  • Use nouns not verbs
  • Use plural nouns
Resource GET (read) POST (create) PUT (update) DELETE
/cars Returns a list of cars Create a new ticket Bulk update of cars Delete all cars
/cars/711 Returns a specific car Method not allowed (405) Updates a specific ticket Deletes a specific ticket
/purchase Get al purchases Create a new purchase Bulk update of purschases Delete all purchases
/purchase/85 Returns a purchase Method not allowed (405) Updates a specific purchase Delete all purchases

Resource GET read POST create PUT update DELETE /cars Returns a list of cars Create a new ticket Bulk update of cars Delete all cars /cars/711 Returns a specific car Method not allowed (405) Deletes a specific ticket

Versioning your phrases

A simple way to achieve this is definning the phrase version in the url, like this

{
    "url": "v1/paramsExample/:pathparam",
    "get": { ... }
}

A phrase version should change only if the phrase contract is broken

Reference

Run in a docker container

  • clone repo

  • build image

    docker build -t <username>/corbel-composer .
    
  • run container

    docker run -d -p 3000:3000 --name="corbel-composer"  <username>/corbel-composer
    
  • start/stop container

    docker start/stop corbel-composer
    

Tests

npm test

Coverage

grunt test:coverage

Debug

Requires node-inspector

npm install -g node-inspector
  • Server

    npm run debug
    
  • Tests

    npm run test:debug
    

Example code for phrases

Login a client

if (!req.body || !req.body.jwt) {
  throw new ComposerError('error:jwt:undefined', '', 401);
}
var corbelDriver = corbel.generateDriver({iamToken: ''});

/*
 * Required claims:
 * iss: CLIENT_ID
 * aud: 'http://iam.bqws.io'
 * scope: 'scope1 scope2'
 * exp: epoch + 1h
 */
corbelDriver.iam.token().create({
  jwt: req.body.jwt
}).then(function(response) {
  res.send(response.data);
}).catch(function(err){
  throw new ComposerError('error:unauthorized', err.data, 401);
});

Login a user

if (!req.body || !req.body.jwt) {
  throw new ComposerError('error:jwt:undefined', '', 401);
}
var corbelDriver = corbel.generateDriver({iamToken: ''});

var tokenObject;

/*
 * Request a session token for the user 
 * Required claims:
 * iss: CLIENT_ID
 * basic_auth.username: USERNAME
 * basic_auth.password: PASSWORD
 * aud: 'http://iam.bqws.io'
 * scope: 'scope1 scope2'
 * exp: epoch + 1h
 */
corbelDriver.iam.token().create({
  jwt : req.body.jwt
}).then(function(response){

  //Tenemos el token de usuario, asimismo tambien el refresh y el expires
  tokenObject = response.data;

  //Recreamos el corbelDriver con los settings del usuario
  corbelDriver = corbel.generateDriver({
    iamToken : tokenObject
  });

  //Obtain the logged user data
  return corbelDriver.iam.user('me').get();
}).then(function(response){
  res.send({
    tokenObject: tokenObject,
    user: response.data
  });
}).catch(function(err){
  throw new ComposerError('error:unauthorized', err.data, 401);
});

Refresh a token

if (!req.body || !req.body.jwt) {
  throw new ComposerError('error:jwt:undefined', '', 401);
}

var corbelDriver = corbel.generateDriver({iamToken: ''});


/*
 * Required claims:
 * iss: CLIENT_ID
 * refresh_token: REFRESH_TOKEN
 * aud: 'http://iam.bqws.io'
 * scope: 'scope1 scope2'
 * exp: epoch + 1h
 */
corbelDriver.iam.token().create({
    jwt : req.body.jwt
  })
  .then(function(response){
    res.send(response.data);
  })
  .catch(function(err){
    throw new ComposerError('error:unauthorized', err.data, 401);
  });

Return current user info

corbelDriver.iam.user('me').get();

Code snippets

Code snippets are a minor form of phrases, they are accesible through the compoSR object on your phrases.

You can run your code snippets by executing compoSR.run('snippetName', params); where params is anything you want it to be. From your snippets you will be allowed to access to the params variable and the compoSR object itself.

compoSR will be allowed to access any snippets defined in your domain and your parent domains.

For example, _silkroad:composer will be able to access all the _silkroad:composer snippets and all the _silkroad snippets. If a snippet has the same name on both of the domains, the one with a deepest hierarchy will overwrite the first one.

Let's take a look at it:

  • Given this snippets:
var snippets = {
  'domainName' : [
    {
      name : 'myFunction',
      code : 'compoSR.run("hello", "world")'
    },
    {
      name : 'hello',
      code: 'console.log(params);'
    }
  ],
  'domainName:childDomain' : [
    {
      name : 'hello',
      code: 'console.log("I am the child: ", params);'
    }
  ],
}
  • If we run the myFunction snippet, accesing from a client that belongs to the domain named domainName:childDomain it will show this:
compoSR.run('myFunction');
//=> I am the child: world
  • If the client or user belongs to the domain named domainName and we execute the same function we'll get:
compoSR.run('myFunction');
//=> hello world

Logs

Logs are written to the linux syslog and in the logs folder.

You can set logFile and logLevel in your config file.

Available log levels can be found at winston's npm page:

  • debug
  • info
  • warn
  • error

You can disable syslog by setting syslog property to false in the config file.

Package Sidebar

Install

npm i corbel-composer@0.0.9

Version

0.0.9

License

Apache-2.0

Last publish

Collaborators

  • antai
  • bq-devtools
  • danigar
  • rafinskipg