Git Product home page Git Product logo

chainy's Introduction

Chainy

Build Status NPM version Dependency Status Development Dependency Status
Gittip donate button Flattr donate button PayPayl donate button BitCoin donate button Wishlist browse button

Perhaps the most awesome way of interacting with data using a chainable API

Install

  • Use: require('chainy')
  • Install: npm install --save chainy
  • Use: require('chainy')
  • Install: npm install --save chainy
  • CDN URL: //wzrd.in/bundle/[email protected]
  • Use: require('chainy')
  • Install: ender add chainy

Usage

Find the complete documentation for Chainy at the wiki

// chainy install set map swap
require('chainy').create()
	.set(['some', 'data'])
	.map(function(item, next){
		return next(null, item.toUpperCase())
	})
	.action(function(item, next){
		return next(null, item.join(' ')+'!')
	})
	.done(function(err, result){
		if (err)  throw err
		console.log('result:', result)  // result: SOME DATA!
	})

History

Discover the change history by heading on over to the HISTORY.md file.

Contribute

Discover how you can contribute by heading on over to the CONTRIBUTING.md file.

Backers

Maintainers

These amazing people are maintaining this project:

Sponsors

No sponsors yet! Will you be the first?

Gittip donate button Flattr donate button PayPayl donate button BitCoin donate button Wishlist browse button

Contributors

These amazing people have contributed code to this project:

Become a contributor!

License

Licensed under the incredibly permissive MIT license

Copyright © 2014+ Bevry Pty Ltd [email protected] (http://bevry.me)

chainy's People

Contributors

balupton avatar dcohenb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chainy's Issues

Figure out a way to remove the requirement of the chain's data as the first argument

Let's take the set action:

require('chainy').require('log')
    .addExtension('set', 'action', function(value, newValue){
        return newValue
    })
    .create()
    .set('blah')
    .log()  // blah

It needs to accept that value argument, as there is no way to turn it off.

Unfortunately, the new args taskOption added in v1.5.0 of Chainy, won't cover it, as:

Chainy.require('log')
    .addExtension('set', {
        type: 'action',
        taskOptions: {
            args: []
        }
    }, function(value, newValue){
        return newValue
    })
    .create()
    .set('blah')
    .log()  // null

Will output null as no arguments would be received.


This is something that I was considering about when releasing v1.5.0, however, v1.5.0 is still and improvement and offers cool stuff, despite this oversight.


What we probably need to do, is add a new special argument, like Chainy.injectArgumentsAsArguments, and Chainy.injectArgumentsAsArgument, then change the default action args to [Chainy.injectChainDataAsArgument, Chainy.injectArgumentsAsArguments].

This should maintain a lot of backwards compat, introduce some power, and accomplish the use case. With args: [] being changed to args: [Chainy.injectArgumentsAsArguments] instead.


The other option is to allow for args: false to be a special case, which means don't apply the action default arguments, but still apply the task options default arguments.


Another approach, which is similar to the args: false suggestion, which I initially coded before v1.5.0 but then dropped, was a new task extension type, and a new chain.task(method, opts). That will be the same as the action extension, but without the argument requirement. However, after implementation it proved to be an anti-pattern to a sort, as the user should have control over the argument insertion for the most part, and could cause confusion for implementors about which type they want. However, considering v1.5.0 is out with new args handling, this could be worth reconsideration as the anti-pattern may be subverted by the new args handling.


Need to consider this and weigh it up.

Abstract out plugins into their own repos/packages

Questions:

  1. What namespace should they use: chainy-pluginname, or chainy-plugin-pluginname
  2. Should this be for all plugins? or just plugins that aren't common or have deps?
  3. Should direct inclusion even be allowed?

Makes action extensions behave more like swap

I was just left mystified by the fact that my .done(next) in a plugin was not applying the value to the chain. Needless to say, that is how swap works, not action extensions.

We should make action extensions behave more like swap.

The question here then becomes, should action extensions first argument be the chain's value like in swap (a breaking change to existing plugins), or should action extensions still use this.data. I'm quite in favour of using swap syntax for all the things.

revaluate if the split of chainy and chainy-core was a good idea

after doing a whole bunch of plugins, and using chainy heavily, I'm not convinced that the split of chainy and chainy-core was a good idea

For instance, one can just do require('chainy-core').create().require('autoload') — the autoload plugin wasn't around when myself and @JedWatson first started debating the need of a split

@JedWatson what are your latest thoughts on this? Can I convince you a split is a bad idea in hindsight?

Add a logo

Ideal:

  • find a designer
  • plead with them to create a logo
  • hug them dearly

Ideas from the non-designers:

  • a block style C made out of chains
  • an E shaped out of chains, chain-eee
  • a fork symbol shaped out of chains, to showcase the asynchronous nature of it
  • a series of linked chains

Resources:

Should set be bundled? Should map be bundled?

Should they be plugins at all?

Should they be plugins and peerDeps of chainy?

Should they be plugins and included in the common bundle?

Should chainy include the common bundle?

Should they not be plugins, and just bundled directly in the chainy-core code?


Advantage of plugins, separation makes it easier to innovate, release, and test them.

Advantage of bundling with chainy, easier to use as they are already there.

The advantage of bundling with chainy can be accomplished by having them as plugins, and including them with chainy either as plugins, as part of the common bundle.

Figure out `"use strict";`

Considering the official way to use chainy on the client side is via browserify, we could probably remove out self executing function wrappers on all our code, and just make the first line "use strict"; without any wrappers. This is because node.js automatically wraps our modules, and browserify does too.

This change needs to be applied to all chainy code, tests and plugins.

Create a plugin to be able to require non chainy namespaced modules

Considering we can now do module.exports.extension = {}, it would be nice if we could require standard npm modules too. I'm thinking this could be a plugin that is added to the chainy package. It would allow us to do the following:

require('chainy').create().require('lodash.flatten set log')
    .set([1,[2,3],4]).flatten().log() // [1,2,3,4]

The potential for this is to finally stop having framework specific plugins being created, instead we can just update existing modules with the required configuration, that then works in different frameworks.

It would also allow us to create our own cli tools using chainy, then have them themselves be chainy plugins too, without the chainy-plugin- namespace. E.g. geojson-github-communities bevry docpad chainyjs could be a CLI tool, but also a chainy plugin without the need for chainy-plugin-geojsongithubcommunities. Instead, you do chainy install geojson-github-communities, and in chainy .require('geojson-github-communities') and it works as expected. Probably attempting for a chainy-plugin first, and then falling back on without one if not.

One side issue here, is that things like chainy-plugin-map etc, use this.create(), now this inheritance is important as it allows for greater debugging due to the tracking of children and parents. If we were to do require('chainy-core').create() it is now true that the plugin would be standalone, but it would lose it's inheritance abilities. Perhaps what we need is this: require('chainy-core').create().inherit(this), which then sets up the parent etc, while maintaining standalone abilities.

Feedback

Use this issue to provide general feedback for Chainy.

Chainy CLI

One of the big reasons for why Chainy is awesome, it that it makes combining things easy.

It would be cool to do something like:

chainy action gitremotes | chainy action exec 'git push $0'

The advantage of this over noflo, is that we don't have to change our entire programming paradigm in order to support stdin. We just use conventions, then wrap them according to type.

However, for the above example, the following is suitable:

git remote | xargs -L1 git push

So I wonder if there is a better use case for this.

Chainy data type checking troubles

Howdy, I've been trying to do a type check in my data before it runs through a chainy.each() but the way it is now it keeps thinking the data in chainy.set() is the entire object and it doesn't each() through it. However .set(data) was the exact same way I had it written before my type checking so am not sure what's going astray here:

// ... ^

    let Chainy = require('chainy').subclass().require('set feed each');
    let chainyInstance = Chainy.create();

    if (Object.prototype.toString.call(data) === '[object Object]'){
        chainyInstance.set(data);
    } else if (Object.prototype.toString(data) === '[object String]'){
        chainyInstance.set(data).feed();
    }

    chainyInstance
        .each((itemValue, itemIndex, complete) => {
            let name = mpath.get(item_name, itemValue);
            debugger;
            fs.appendFile(path, template(itemValue, name), (err) => {
                if (err) throw err;
                console.log(`The ${name} was appended to file!`);
            });
            complete();
        }).done(function(err, result){
                if (err)  throw err;
                return false; // For testing.
                // console.log('result:', result);  // result: SOME DATA!
        }); 

// ... v

Thanks for any tips. 😃

Release v1

It's all coded now, just need to be released.

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.