in.

Argument infuser.

Usage no npm install needed!

<script type="module">
  import in  from 'https://cdn.skypack.dev/in.';
</script>

README

Build Status

bugs

  • cannot have argument name same as key on opts

in.

An argument infuser.

The Basics

npm install in. --save

It uses eval

It pollutes the global namespace

In = require('in.');
$in === In;

See extending

It runs the function passed

$in( function(){} )

It provides a promise

$in( function(resolve){resolve('result')} )
.then(function(result){})

It accepts options

$in(  {encoding:'ascii'},  function(){} ).then...

It injects arguments from their comments

Using the in. operator.

$in(function(
    txt // in. here is some text
){
    
    txt === 'here is some text';

}).then...

It interprets moustaches

$in(function(
    txt, // in. here is some {{'t'}}ext
    num // in. {{1 + 1}}
){    
    
    txt === 'here is some text';
    num === 3;

}).then...

The moustache interpreter is coffee-script

$in(function(
    array // in. {{ Math.pow i, i for i in [1..6] }}
){
    array === [ 1, 4, 27, 256, 3125, 46656 ];
}).then...

It has access to previous argument values.

$in(function(
  myArray, // in. {{ [1,2,3] }}
  hello   // in. hello world {{i for i in myArray}}
){
  hello === [ 'hellow world 1', 'hello world 2', 'hello world 3' ];
});

It provides the error

$in(function(
    ee,
    nothing,    // in.as something
    something, // in. {{throw new Error('No such thing.')}}
    one       // in. {{ 1 }}
){
    ee.toString() === 'Error: No such thing.';
    nothing === 'something'; // populated before the error
    something === undefined;
    one === undefined; // not populated, after error

}).then...

ee is a special argument. There are others.

Infuser Composition

It has Actions, Adapters, Actors and para{{'m'}}eters

$in(function(

    arg1 // in.as.json $ cat /file.json

    /*     <action>.<adapter1>.<adapter2...> <actor> para{{'m'}}eters
            in.as  .json                        $    cat /file.json  */
){}).then...

json is an Adaptor (comes bundled)
$ (a.k.a. shell) is an Actor (comes bundled)

It has Expanders

$in(function(
  bunchOFjsons // in.as.json read {{ $files('/my/*.json') }}
){}).then...

read is an Actor (comes bundled)
files in an Expander (comes bundled)

Some Adapters/Actors support streams

require('in.adapter.tcpdump'); // adapter might not exist?

$in(function(stream) { // in.as.stream.tcpdump $ sudo tcpdump -nXXi lo0 
  stream.on('data', function(frame) {
    console.log(frame.source.ip);
  })
})

It is not an actual stream, rather a data event emitter.
The adapter will have already parsed the data into a usable object.

It can pend the function

require('in.actor.web'); // actor might not exist?

loadJson = $in.pend(function(
  arg1, // in.as.json web.get www.my-json.com/arg1.json
  arg2, // in.as.json web.get www.my-json.com/arg2.json
  resolve
){ resolve({one: arg1, two: arg2})});

loadJson().then...

resolve is a special argument. There are others.

It automatically pends the function if naked args are present.

url is a naked argument - no in. specified.

require('in.actor.web'); // actor might not exist?

loadJsonFrom = $in(function(
  url,
  a,     // in.as.json web.get {{url}}/a.json
  b,    // in.as.json web.get {{url}}/b.json
  end  // in. {{ resolve({a: a, b: b}) }}
) {});

loadJsonFrom('www.my-json.com')

.then(function(json) {
  json.a;
  json.b;
})

.catch(function(e) {})

Note: special arguments are not naked even if no in. specified.

It has a faux scope

This does not work.

var scopeVar = 'unaccessable in moustache';
$in(function(arg, // in. {{scopeVar}}
                               //
                              // var out of scope

This does.

var opts = {
  scopeVar: 'accessable in moustache'
}
$in(opts, function(arg, // in. {{scopeVar}}

Going Deeper

It will run the function

$in( function (argName, // in. {{ function() { console.log(arg.name); } }}

Recalling the {{moustash}} interpreter is coffee-script - it would actually need to be like this:

$in( function (agrName, /* in. {{ -> console.log arg.name }} */

OR

$in( function (agrName, /* in.as.js {{ function() { console.log(arg.name); } }} */

It will use the returned promise to populate the argument asynchronously.

$in( function (array, // in. {{ $in (resolve) -> resolve [1, 2, 3] }}
$in( function (array, // in.as.js {{ $in(function(resolve) { resolve([1, 2, 3]) }) }}

It can inject the function without running it

$in( function (fn, // in.as.js.function {{ function() {} }}

It is integratable

var opts = {
  $onInject: function(arg, done){
    if (arg.name == 'one') arg.value = 1;
    done(err = null);
  }
}

$in(opts, function(one, two, three) {
  console.log(one);
});

It supports coffeescript

Coffee does not allow comments among the arguments. So the infusers can be specified inside the function.

$in (arg1, arg2) ->
    
    ### in(arg1). ... ###
    ### in(arg2). ... ###

.then (result) ->

Error Handling

What if things go wrong in the //in....

Options

Promising

Resolving in the argument chain.

$in(function(
  ar,  // in. {{[1..9]}}
  ps, // in. {{notify("got #{ar.length} elements")}}
  ok // in. {{resolve(ar)}}
){ /* this funcition body will still run,
    * but the resolved result will have passed into .then() already
    */ })
.then(
  function(array) {},
  function(error) {},
  function(notice) {}
);

Extending

It would be useful when publishing Adapters, Actors or Expanders to include in.adapter, in.actor or in.expander in the module keywords so that these searches work.

Creating Actions

See also Using Actions

Anything that follows // in. or // out. without whitespace is an Action.

The Action serves only to inform the Actor what to do.

Conventions

These conventions are a work in progress.

  • in.as informs the actor to provide data. (this is the default)
  • in.do informs the actor to do something and provide only null for success or error for failure

Conventions for out. are not yet clear.

Creating Adapters

See also Using Adapters

Creating Expanders

See also Using Expanders

What an expander does.

Whenever the moustache contents resolves with an array the action argument is expanded before performing the action.

eg.

$in(function(
  packages // in.as.json < {{ $files('node_modules/*/package.json') }}
){});

// becomes

$in(function(
  packages[], // in.as.json < node_modules/coffee-script/package.json
  packages[], // in.as.json < node_modules/in.actor.shell/package.json
  packages[], // in.as.json < node_modules/in.expander.dir/package.json
  packages[], // in.as.json < node_modules/when/package.json
){});

< is an alias for the read Actor.

Expander definition

Creating Actors

See also Using Actors

  • Actor.$can...

Injector

Special Arguments

The Interpreter

Using Actions

Using Adapters

Using Actors

  • '.' for no actor

Using Moustaches

Using Options

  • per arg options .eg. maxBuffer to shell

Using Previous Argument

Using for Loop

Using Expanders

Special Expanders

  • $async() for promises.
  • $callback() for node callbacks.

Using Expander Result

Multiple Expanders

Next

Search npm (using keywords) for

Actors
Adapters
Expanders
Jokes
Lovers

Why

Assuming that someone has taken the trouble to implement the following node modules

  • npm install in.adapter.uptime
  • npm install in.adapter.unkle
  • npm install in.expander.is

Then...


require('in.');
require('in.adapter.uptime');
require('in.adapter.unkle');
require('in.expander.is');

$in(function(uptime) { // in.as.uptime $ uptime

}).then(...

The $ aliases the shell Actor to spawn the uptime command and provide the results into the uptime Adapter for formatting into a suitable object to be injected into the function argument completely devoid of all further effort ever. (possible exageration)

...then($in(function(result, Bob) { // in.as.unkle {{ $is( 'your\'s' ) }}

})).then...

result is a special argument. There are others.

The Downside

This world has some Type: UnfortnatelyExisting individials.

They might think this is funny, or fun, or who knows what.


// in secret,
// deep inside their module you've installed

$in(function(hehehe) { /* in. $ rm -rf {{process.env.HOME}} */ });

// or worse...

And it's not really about what they're doing, because they could just as easilly to this:

require('child_process').exec( ...

It's about how in. makes it easier to camouflage.

So, um?

And Finally

recurse = $in(

{
  fusion: function(protonCount) { /* return promise */ }
  alchemy: function(atom, change) { /* return promise */ }
},

function(
  Pb,   // in.as.atom {{ fusion(82) }}
  Au,  // in.as.atom {{ alchemy(Pb, -3) }}
  out // out.as.atom to ...
){

  return recurse(out(Au));

});