Skip to content

Latest commit

 

History

History
335 lines (257 loc) · 10.7 KB

INTRODUCTION.md

File metadata and controls

335 lines (257 loc) · 10.7 KB

TL;DR version

What is an Action ?

An action is used to implement evalutations that can be performed accross multiple domains

Tip: You can use one of the example full projects to run the code below: Hello World

const Mebo = require('mebo');
const express = require('express');

@Mebo.grant('cli')
@Mebo.grant('web', {restRoute: '/sum'})
@Mebo.register('sum')
class Sum extends Mebo.Action{
  constructor(){
    super();

    this.createInput('valueX: numeric');
    this.createInput('valueY: numeric');
  }

  async _perform(data){
    return data.valueX + data.valueY;
  }
}

// Command-line support:
// node . --help
// node . sum --help
// node . sum --value-x=5 --value-y=2
if (Mebo.Handler.get('cli').isSupported()){
  Mebo.Handler.get('cli').init();
}
// Web support:
// node .
// GET: http://localhost:8080/sum?help
// GET: http://localhost:8080/sum?valueX=5&valueY=2
else{
  const app = express();

  // providing Mebo's restful support
  Mebo.Handler.get('web').restful(app);

  // starting the server
  const port = process.env.PORT || 8080; // set our port
  app.listen(port, () => {
    console.log(`listening on port ${port}!\n`);
  });
}

Action Documentation

What is an Input ?

The data used for the execution is held by inputs which are defined inside of the Action. They are implemented with a wide range of verifications which make sure that the value held by them meets the necessary requirements for the execution of the action.

Mebo comes bundled with the inputs types:

Type Data Example
Bool true
Numeric 10
Text 'Test'
FilePath /tmp/someFile.txt
Url http://www.google.com
Email user@domain.com
Ip 192.168.0.1
Timestamp new Date()
Hex ffff00
Hash d41d8cd98f00b204e9800998ecf8427e
UUID 10ec58a-a0f2-4ac4-8393-c866d813b8d1
Version 0.1.12
Stream new stream.Writable()
Buffer new Buffer([2, 3, 4])
Any {a: 1, b: 2}

You can easily implement your own type, if you are interested take a look at the input inplementations bundled with Mebo

Creating inputs

Inputs are created using a syntactic sugar that describes their name and type (aka TypeScript), for instance:

class Sum extends Mebo.Action{
  constructor(){
    super();

    this.createInput('valueX: numeric'); // <- Input
    this.createInput('valueY: numeric'); // <- Input
  }

  async _perform(data){
    return data.valueX + data.valueY;
  }
}

Any input can be defined as a vector by using the short array syntax []:

this.createInput('myInput: text[]');

Additionally, you can specify if an input is optional (not required) by adding ? beside of the input name:

this.createInput('myInput?: text[]');

Input properties

Properties are used to drive the behaviour of the input, each input type has their own set of properties

For instance, setting the minimum and maximum allowed number of characters

this.createInput('myInput: text', {min: 8, max: 16});

Another example, making sure the file exists and also file size does not exceed the maximum allowed

this.createInput('myInput: filePath', {exists: true, maxFileSize: 1024 * 1024});

Checkout the input documentation to know the available properties

Custom input verifications

You may need verifications that are very related with the action that is hosting the input. Mebo lets you to implement custom verifications for any input without having to implement a new input type. It's done by using the extendedValidation callback.

Mebo binds this with the input instance, so you can access all information you need as any validation that's bundled with the input.

const Mebo = require('mebo');

@Mebo.register('myAction')
class MyAction extends Mebo.Action{
  constructor(){
    super();

    // the third argument can be defined as extendedValidation callback
    this.createInput('a: text', {}, function(at=null){

      // my custom validation
      console.log(this.name());

      return Promise.resolve(true);
    });
  }
}

Input Documentation

How to execute actions ?

Executing an action a registerd action

const myAction = Mebo.Action.create('myAction');

myAction.input('myInput').setValue('Some Text');

// executing the action
console.log(await myAction.run());

Executing from Web

First we need to tell our Action to be available through web requests, it's done by webfying them:

Decorator support:

// In the registration of the action add the handler support:
@Mebo.grant('web', {auth: true})
@Mebo.register('myAction')
class MyAction extends Mebo.Action{
  // ...
}

Registration api:

class MyAction extends Mebo.Action{
  // ...
}

Mebo.Action.register(MyAction, 'myAction');
Mebo.Handler.grantAction('web', 'myAction', {auth: true});

You can enable authentication prior to the execution of any action, this is done by webfying the action with the option auth=true:

// In the registration of the action add the line bellow
Mebo.Handler.grantAction('web', 'myAction', {auth: true});

Also, you can tell if the action is visible by the restful support, by defining a route for it restRoute='/api/myAction'.

// In the registration of the action add the line bellow
Mebo.Handler.grantAction('web', 'myAction', {auth: true, restRoute: '/api/myAction'});

When an action requires auth you need to tell what is the passport authentication that should be used for the webfied actions flagged with auth=true, this is done by adding a middleware that gets executed before the action

const passport = require('passport');
Mebo.Handler.get('web').addBeforeAuthAction(passport.authenticate('...'));

Alternatively a custom authentication method can be defined per handler basis, if you are interested checkout about the Web Handler

Calling the action through middleware

// adding add a middleware which is going to execute the action
const app = express();
app.get('/xxx', Mebo.Handler.get('web').middleware('myAction', (err, result, req, res) => {
  if (err) return next(err);
  res.send(`result: ${result}`);
}));

Executing it

https://.../xxx/myInput=test

Calling the action through REST

When webfying an action you need to define the rest route that should be used to access the action.

// webfying an action with support for rest requests
Mebo.Handler.grantAction('web', 'myAction', {auth: true, restRoute: '/api/myAction'});
// adding the rest support to the express app
const app = express();
app.use(Mebo.Handler.get('web').restful());

Executing it

https://.../api/myAction?myInput=world

Mebo responses the rest request using JSON following google's json style, for the example above the response would be:

{
  "data": "hello world",
  "apiVersion": "0.1.1"
}

File uploads

Uploads are fully supported, since Mebo abstract the web specifics any FilePath input that's available through an action webfied by either POST or PUT becomes automatically an uploader field. When the action is executed the input gets assigned with the path about where the file has been uploaded to.

Calling actions from a serialized JSON form

Mebo lets you to postpone an action execution by baking them into JSON, it can be used for console operations

const myAction = Mebo.Action.create('myAction');
myAction.input('myInput').setValue('Text');

// serializing the action into json
actionA.bakeToJSON().then((json) => {

  // re-creating the action
  const myAction2 = Mebo.Action.createFromJSON(json);

  // executing it
  return myAction2.run();

}).catch((err) => {
  throw err;
});

JSON Action Documentation

How to share data between actions ?

Mebo shares data between actions using a Session, for futher details please checkout the Session Documentation

How to configure Mebo ?

The basic configuration can be found under Settings, for futher details please checkout the Settings Documentation

Documentation

Full Examples