npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

coroutiner

v0.3.3

Published

Transforms generator functions into coroutines

Downloads

102

Readme

Coroutiner

A convenience transformer to turn every GeneratorFunction into a Promise.coroutine.


coroutiner = require('coroutiner')

obj = {
	fn: function*() {
		yield Promise.delay(500)
		return new Promise(function(resolve) { resolve(1000) })
	}
	
	normalFn: function() { return 5 }
}

coroutiner( obj )

obj.fn().then(function(number) {
	number // returns 1000
})


Promise.coroutine(function*() {
	yield obj.fn() // returns 1000
}

obj.normalFn() // returns 5

Why?

Instead of calling Promise.coroutine on every generator function, just call coroutiner on a parent object. This allows one to build an application utilizing yield much more conveniently when every generator is already promisified.

Just be careful what you run this over. When prototype: true (default) is enabled this will work on class (){}.prototype, function(){}.prototype and {}.__proto__, which includes instances of classes.

You can also do it recursively.

// Create a new coroutiner, which also enumerates over a functions prototype
coroutiner = require('coroutiner')

fn = function*() {}
fn.prop = 1

obj = {
	fn: fn
	anArray: [
		{
			fn: function*(){} // coroutined, due to { array: true }
		}
	]
	klass: class Class {
		fn: function*() {} // coroutined, due to { prototype: true }
	}
}

// This is run on every matched GeneratorFunction
// Returning `false` will skip it from being transformed
validatorFunction = function(key, value, parent) {
	if ( key.match(/idontwantyou/) ) {
		return false // skipping
	}
}

coroutiner.all(obj, validatorFunction)

// Properties of GeneratorFunctions will be copied over
obj.fn.prop // returns 1

Caveats and Warnings

Coroutiner will behave weirdly in this CoffeeScript example

class Test
	fn: => 
		# A bound function!
		yield return
		
class NewTest extends Test
	newFn: -> yield return

test = new NewTest()

coroutiner { test, NewTest }

yield test.fn() # Error, because .fn() never got coroutined before being extended
yield test.newFn() # Works because it was defined in NewTest's prototype
yield new NewTest().fn() # Works because the instance was created with the coroutined prototype

The transformer

Make sure require('bluebird') works if you aren't specifying your own transformer. Bluebird's Promise.coroutine is used as a transformer by default, but by creating your own coroutiner instance that can change.

coroutiner( obj, ?validatorFn?, ?types? )

Returned by require('coroutiner').

Transforms GeneratorFunctions within the obj with the transformer. Will also enumerate over the fn.prototype if prototypes are enabled.

This is not recursive.

coroutiner.all( obj, ?validator?, ?depth?, ?types? )

Recursively transforms properties, like coroutiner(). Be careful with this. Only run it over an object that exposes your generators. If this touches a library that expects generators then things will break.

coroutiner.Coroutiner( options )

Creates a new coroutiner instance.

options {Object}

  • validator {Function} A default validator function
  • transformer {Function} A default transformer instead of Promise.coroutine
  • array {Boolean} true Whether to iterate over arrays items
  • object {Boolean} true Whether to iterate over object properties
  • function {Boolean} true Whether to iterate over function properties
  • prototype {Boolean} true Whether to iterate over function/object prototypes

This controls which properties are enumerated over to look for transformable properties.

coroutiner.create( fn, ?types? )

Create a coroutined function and copies over its properties into a new returned function. This is called by coroutiner() and coroutiner.all()

coroutiner.types

{
	object: true, function: true, array: true
	prototype: true, unowned: true, circular: false
}

unowned as false if you only want .hasOwnProperty properties circular as true will remove cyclic recursion protection