GithubHelp home page GithubHelp logo

kusanagi / katana-sdk-node Goto Github PK

View Code? Open in Web Editor NEW
4.0 9.0 5.0 286 KB

Node.js SDK for the KATANA Framework

Home Page: https://kusanagi.io

License: MIT License

JavaScript 100.00%
nodejs sdk framework katana kusanagi

katana-sdk-node's Introduction

KATANA SDK for Node.js

version Build Status Coveralls Coverage Status license

Node.js v6 SDK to interface with the KATANA™ framework (https://kusanagi.io).

Requirements

  • KATANA Framework 1.2
  • Node.js 6.0+
  • python (a node-gyp requirement) (v2.7 recommended, v3.x.x is not supported)
  • libzmq 4.1.5+ (including headers, you probably need a libzmq-dev package)

Installation

Make sure the system dependencies are met.

Use the following command to install the SDK from the NPM repository and add it to your dependencies:

$ npm install katana.sdk --save

Alternatively, you might want to install through the yarn package manager:

$ yarn add katana.sdk

To run the tests, determine the code coverage, and pass the linter, run the following:

$ npm run test

Or, you can simply run the tests:

$ npm run test:unit

You can also run the tests and watch for changes, which can be useful when developing:

$ npm run test:dev

If you'd like to generate a code coverage report, run the following:

$ npm run coverage
$ open coverage/lcov-report/index.html

Also, to run the linter on the code base, run the following:

$ npm run lint

Finally, if you'd like to build the technical documentation for the code base, you can generate it with the following:

$ npm run docs

Troubleshooting

Make sure these are met before installing the katana.sdk npm package. Some of its dependencies need to be compiled through node-gyp, and these depend on the libzmq headers being present. That means you probably need to install zqm-devel or a similar package (read more). If the katana.sdk npm package was installed before the libzmq header files were present, you'll need to nuke your project's node_modules folder and reinstall katana.sdk.

rm -Rf node_modules
npm install

Getting Started

Include the KATANA™ SDK library and set up Service or Middleware instances, for example:

const Service = require('katana.sdk').Service;

const service = new Service();

Examples

The following is a simple Middleware implementation to handle CORS.

KATANA configurations can be defined as XML, YAML or JSON. For this example we're using JSON.

First, we'll create a new config file for the Middleware as the following:

{
  "@context": "urn:katana:middleware",
  "name": "cors",
  "version": "1.0.0",
  "request": true,
  "engine": {
    "runner": "urn:katana:runner:node",
    "path": "cors.js"
  }
}

Note that you can also use a remote debugger by adding the --debug-brk flag as the value of the interpreter-options property of the engine element of the configuration, for example:

{
  "@context": "urn:katana:middleware",
  "name": "cors",
  "version": "1.0.0",
  "request": true,
  "engine": {
    "runner": "urn:katana:runner:node",
    "path": "cors.js",
    "interpreter-options": "--debug-brk=8888"
  }
}

Now we'll need to create the logic for the Middleware in the cors.js file, as defined in the config file:

const Middleware = require('katana.sdk').Middleware;

const middleware = new Middleware();

middleware.request((request) => {
  const httpRequest = request.getHttpRequest();
  const httpMethod  = httpRequest.getMethod();
  const urlPath     = httpRequest.getUrlPath();
  if (httpMethod === 'OPTIONS') {
    const response     = request.newResponse(200, 'OK');
    const httpResponse = response.getHttpResponse();
    httpResponse.setHeader('Access-Control-Allow-Origin', '*');
    httpResponse.setHeader('Access-Control-Allow-Headers', 'cache-control');
    httpResponse.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE, PUT');
    return response; // exit early
  }
  return request;
});

middleware.run();

This Middleware can now be included in any Gateway to enable CORS processing.

In the following example we'll create a Service which provides a simple CRUD interface for users:

{
  "@context": "urn:katana:service",
  "name": "users",
  "version": "1.0.0",
  "http-base-path": "/1.0.0/users",
  "info": {
    "title": "Users Service"
  },
  "engine": {
    "runner": "urn:katana:runner:node",
    "path": "users.js"
  },
  "action": [
    {
      "name": "list",
      "collection": true,
      "http-method": "get"
    },
    {
      "name": "create",
      "http-method": "post",
      "http-input": "form-data",
      "param": [
        {"name": "name", "required": true}
      ]
    },
    {
      "name": "read",
      "http-method": "get",
      "http-path": "/{id}",
      "param": [
        {"name": "id", "type": "integer", "required": true, "http-input": "path"}
      ]
    },
    {
      "name": "update",
      "http-method": "put",
      "http-path": "/{id}",
      "param": [
        {"name": "id", "type": "integer", "required": true, "http-input": "path"},
        {"name": "name", "required": true, "http-input": "form-data"}
      ]
    },
    {
      "name": "delete",
      "http-method": "delete",
      "http-path": "/{id}",
      "param": [
        {"name": "id", "type": "integer", "required": true, "http-input": "path"}
      ]
    }
  ]
}

And as before, we'll create the Service logic in a file named users.js, as we had defined in the config file:

const Service = require('katana.sdk').Service;

const service = new Service();

service.action('list', (action) => {
  // get all entities from the data store
  action.setCollection(collection);
  return action;
});

service.action('create', (action) => {
  const name = action.getParam('name').getValue();
  // create entity in data store with "name"
  action.setEntity(entity);
  return action;
});

service.action('read', (action) => {
  const id = action.getParam('id').getValue();
  // get entity from data store with "id"
  action.setEntity(entity);
  return action;
});

service.action('update', (action) => {
  const id = action.getParam('id').getValue();
  const name = action.getParam('name').getValue();
  // update "name" in data store for "id"
  return action;
});

service.action('delete', (action) => {
  const id = action.getParam('id').getValue();
  // delete from data store with "id"
  return action;
});

service.run();

Documentation

See the API for a technical reference of the SDK.

For help using the framework see the documentation.

Support

Please first read our contribution guidelines.

We use milestones to track upcoming releases inline with our versioning strategy, and as defined in our roadmap.

For commercial support see the solutions available or contact us for more information.

Contributing

If you'd like to know how you can help and support our Open Source efforts see the many ways to get involved.

Please also be sure to review our community guidelines.

License

Copyright 2016-2018 KUSANAGI S.L. (https://kusanagi.io). All rights reserved.

KUSANAGI, the sword logo, KATANA and the "K" logo are trademarks and/or registered trademarks of KUSANAGI S.L. All other trademarks are property of their respective owners.

Licensed under the MIT License. Redistributions of the source code included in this repository must retain the copyright notice found in each file.

katana-sdk-node's People

Contributors

fcastilloes avatar nullproxy avatar orestes avatar rvegas avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

katana-sdk-node's Issues

Parameters set in a first middleware are lost in a second one

When more than one Middlewares are registered and one sets a parameter using the request.setParam() method, the next one loses it, so if it is not set again it never gets to the Service.

If the last Middleware sets the parameter it works ok, so it looks like the issue is in the Middleware reading existing parameters in the transport.

Service action not working all the time

Related to #4

Given the same source examples from the related issue, now the SDK is behaving improperly:

Sometimes it's simply giving an Operation failed message:

2017-06-05T11:54:04.717Z [INFO] Component initiated...
2017-06-05T11:54:04.719Z [DEBUG] Running SDK: node runner.js --name auth --component service --framework-version 1.0.17 --version 1.0.0 --socket @katana-service-auth-1-0-0 --debug
2017-06-05T11:54:06.229Z [DEBUG] Component running: PID 7123
2017-06-05T11:54:06.230Z [DEBUG] Calling component with timeout: 1.0s
2017-06-05T11:54:07.277Z [ERROR] Component communication timeout
2017-06-05T11:54:07.278Z [DEBUG] Component shutdown...
2017-06-05T11:54:07.331Z [ERROR] Operation failed

And if I run it consecutively, it logs again something related to the middleware:

vagrant@ansible ~/dev/katana  $ katana service action -c config/katana.xml -n facebook -p access_token='123' --debug 
2017-06-05T11:54:14.543Z [INFO] Component initiated...
2017-06-05T11:54:14.544Z [DEBUG] Running SDK: node runner.js --name auth --component service --framework-version 1.0.17 --version 1.0.0 --socket @katana-service-auth-1-0-0 --debug
2017-06-05T11:54:16.052Z [DEBUG] Component running: PID 7138
2017-06-05T11:54:16.053Z [DEBUG] Calling component with timeout: 1.0s
2017-06-05T11:54:17.035Z [ERROR] Middleware error running callback: facebook. Cannot get service schema. No mapping provided
2017-06-05T11:54:17.035Z [DEBUG] Component shutdown...
2017-06-05T11:54:15.689Z [DEBUG] [SDK] No custom startup callable has been set
2017-06-05T11:54:15.691Z [DEBUG] [SDK] Socket bound: ipc://@katana-service-auth-1-0-0
2017-06-05T11:54:15.692Z [DEBUG] [SDK] Monitoring socket: ipc://@katana-service-auth-1-0-0
2017-06-05T11:54:17.044Z [DEBUG] [SDK] ZMQ socket event 'accept' [ 19, 'ipc://@katana-service-auth-1-0-0' ]
2017-06-05T11:54:17.044Z [DEBUG] [SDK] ZMQ socket event 'disconnect' [ 19, 'ipc://@katana-service-auth-1-0-0' ]
2017-06-05T11:54:17.048Z [DEBUG] [SDK] No custom shutdown callable has been set
2017-06-05T11:54:17.062Z [ERROR] Operation failed

This behaviour is not correct since I think most of the code in the service action is being executed, but the results are not correct. Even if this is an empty response, I think other SDKs return the transport as it is after completing.

Service action not working properly

When running a service action, the SDK is returning a non-related error:

vagrant@ansible ~/dev/katana  $ katana service action -c config.xml -p access_token="123" -n facebook
2017-05-05T07:24:05.407Z [INFO] Component initiated...
2017-05-05T07:24:07.527Z [ERROR] Middleware error running callback: facebook. Cannot get service schema. No mapping provided
2017-05-05T07:24:07.559Z [ERROR] Operation failed```

This is coming from very simple config and runner files:

config.xml

<?xml version="1.0" encoding="UTF-8"?>
<service xmlns="urn:katana:service" name="auth" version="1.0.0" http-base-path="/1.0/auth">
    </info>
    <engine runner="urn:katana:runner:node" path="./runner.js"/>
    <action name="facebook" http-method="post" http-input="form-data" http-path="/facebook" description="logs in via facebook">
        <param name="access_token" required="true" description="The access token of the user in fb"/>
        <schema type="entity" name="auth"/>
    </action>
    <schema-entity name="auth">
        <entity validate="true">
            <field name="token"/>
            <field name="refresh_token"/>
            <field name="expires" format="datetime"/>
        </entity>
    </schema-entity>
</service>

runner.js

const Service = require('katana.sdk').Service;

const service = new Service();

service.action('facebook', (action) => {
    let graph = require('fbgraph');
    const token = action.getParam('access_token').getValue();
    graph.setAccessToken(token);
    graph.get('me?fields=id,email,location,picture', function (error, response) {
       action.log(response);
    });
    return action;
});

service.run();

Middleware Fails when called from gateway

With this config:

<?xml version="1.0" encoding="UTF-8"?>
<middleware xmlns="urn:katana:middleware" name="api" version="1.0.0" protocol="urn:katana:protocol:http" request="true" response="true">
    <info title="Auth" description="Response middleware for API requests and responses" terms="https://tech.example.com/docs/middleware-api">
        <contact name="API" url="https://tech.example.com/docs/middleware-apii" email="[email protected]"/>
        <license name="License" url="https://tech.example.com/docs/middleware-api"/>
    </info>
    <external-docs description="API middleware docs" url="https://tech.example.com/docs/middleware-api"/>
    <engine runner="urn:katana:runner:node" path="../runner.js"/>
    <http-response code="401" description="The access credentials were invalid" mime="application/problem+json">
        <http-example>
            <![CDATA[
            {
              "type": "https://tech.example.com/api/errors#401-Unauthorized",
              "detail": "The access credentials used on this request are not valid",
              "status": 401,
              "title": "Unauthorized"
            }
            ]]>
        </http-example>
    </http-response>
</middleware>

And this code:

const Middleware = require('katana.sdk').Middleware;
const middleware = new Middleware();

middleware.request((request) => {
    return request;
});

middleware.response((response) => {
    return response;
});

middleware.run();

The gateway calls return this error on any type of request:

2017-06-09T07:58:40.104Z [ERROR] [SDK] Error running callback: response. Cannot read property 'v' of undefined TypeError: Cannot read property 'v' of undefined
at Mapper.getHttpRequest (/home/vagrant/dev/katana/middleware-api/node_modules/katana.sdk/sdk/mapper.js:101:20)
at Middleware._getResponse (/home/vagrant/dev/katana/middleware-api/node_modules/katana.sdk/sdk/component.js:234:20)
at Middleware._processCommand (/home/vagrant/dev/katana/middleware-api/node_modules/katana.sdk/sdk/middleware.js:30:33)
at Middleware._processMessage (/home/vagrant/dev/katana/middleware-api/node_modules/katana.sdk/sdk/component.js:142:10)
at emitThree (events.js:116:13)
at emit (events.js:194:7)
at Socket._flushRead (/home/vagrant/dev/katana/middleware-api/node_modules/zmq/lib/index.js:638:15)
at Socket._flushReads (/home/vagrant/dev/katana/middleware-api/node_modules/zmq/lib/index.js:676:23)
at _zmq.onReadReady (/home/vagrant/dev/katana/middleware-api/node_modules/zmq/lib/index.js:297:10)

If I run katana middleware request -c config/katana.xml -u http://test.com/1.0/auth/facebook it works as expected.

Release 1.2.4

Merge all PRs and release 1.2.4 on GitHub and npm

Action/Response .getTransport() broken due to Object.freeze()

Both in:

/**
*
* @return {Transport}
*/
getTransport() {
return Object.freeze(this._transport);
}

And in:

/**
*
* @returns {Transport}
*/
getTransport() {
return Object.freeze(this._transport);
}

These calls to Object.freeze() are making the transport inaccessible in both classes.

From the documentation here, this is the cause:
// Both the object being passed as well as the returned // object will be frozen. It is unnecessary to save the // returned object in order to freeze the original.

@orestes I don't want to rush an issue so for now I'll just remove it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.