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

strain

v0.8.5

Published

defines callable, method-chained js components

Downloads

27

Readme

strain

Build Status

defines callable, method-chained js components, inspired by d3's pretty api.

var strain = require('strain');


var thing = strain()
  .prop('foo')
    .default(22)
  .prop('bar')
    .default(3)

  .meth('foobar', function() {
    console.log(this.foo() + this.bar());
  });


var subthing = strain(thing)
  .prop('bar')
    .default(23)
    .get(function(v) {
      return v * 2;
    })
    .set(function(v) {
      return v + 1;
    })

  .init(function(arg) {
    console.log('init! ' + arg);
  })

  .invoke(function() {
    console.log('invoke!');
  });


var t = subthing('arg!')  // init! arg!
  .foobar()  // 70
  .bar(42)
  .foobar();  // 108


t();  // invoke!

api

strain([parent])

creates a new type.

var eventable = strain(EventEmitter);

eventable()
  .on('foo', function() {
    console.log('bar');
  })
  .emit('foo');  // bar

if parent is specified, properties on the parent are attached to the type, prototype properties on the parent are accessible via the type's prototype, and the parent is attached to the new type as _super_.

.extend()

creates a child type from the calling type. shorthand for strain(<type>).

var thing = strain.extend();
var subthing = thing.extend();

.new()

creates a new instance of the type.

strain()
  .init(function(arg) {
    console.log(arg);
  })
  .new('foo');  // foo

.static(name, value)

defines a new property directly on the calling type.

var thing = strain()
  .static('foo', 23)
  .static('bar', function() {
    console.log('bar!');
  })
  .bar()  // bar!
  .bar();  // bar!

console.log(thing.foo);  // 23

if value is a function that does not return a value or returns undefined, the type is returned instead to allow for further method chaining.

.static(fn)

defines a new method directly on the calling type from a named function.

var thing = strain()
  .static(function bar() {
    console.log('bar!');
  })
  .bar()  // bar!
  .bar();  // bar!

if fn does not return a value or returns undefined, the type is returned instead to allow for further method chaining.

.prop(name)

defines or re-references a new gettable and settable property on a type.

var t = strain().prop('foo')();
console.log(t.foo());  // 23

re-referencing a property allows .default, .set and .get to be applied to a property after it has been defined (possibly by a parent type), without breaking method chaining for the type currently being defined.

.default(v)

sets the default value of the most recently referenced property.

var thing = strain()
  .prop('foo')
  .prop('bar').default(23)
  .prop('foo').default(42);

console.log(thing().foo());  // 42
console.log(thing().bar());  // 23

note that setting mutable values using .default means that all instances of the type will be affected by modifications to the value. .init or .defaults could be used if you need to create mutables per-instance.

.get(fn)

sets the coercion function to use when getting the most recently referenced property.

var thing = strain()
  .prop('foo')
  .prop('bar').get(function(v) {
    return v + 1;
  })
  .prop('foo').get(function(v) {
    return v * 2;
  });

console.log(thing().bar(23).bar());  // 24
console.log(thing().foo(42).foo());  // 84

.set(fn)

sets the coercion function to use when setting the most recently referenced property.

var thing = strain()
  .prop('foo')
  .prop('bar').set(function(v) {
    return v + 1;
  })
  .prop('foo').set(function(v) {
    return v * 2;
  });

console.log(thing().bar(23).bar());  // 24
console.log(thing().foo(42).foo());  // 84

.meth(name, fn)

defines a new method on a type.

var thing = strain()
  .meth('foo', function() {
    return 23;
  })
  .meth('bar', function() {
    console.log(this.foo());
  })();


thing()
  .bar()  // 23
  .bar()  // 23
  .bar();  // 23

if fn does not return a value or returns undefined, the type's instance is returned instead to allow for further method chaining.

.meth(fn)

defines a new method on a type from a named function.

var thing = strain()
  .meth(function foo() {
    console.log('bar');
  })();


thing().foo();  // bar

.defaults(obj)

sets the default values of properties for each new instance using a data object.

var thing = strain()
  .prop('foo')
  .defaults({foo: 23});

console.log(thing().foo());  // 23

.defaults(fn)

sets the default values of properties for each new instance using a function that returns a data object.

var thing = strain()
  .prop('foo')
  .defaults(function() {
    return {foo: 23};
  });

console.log(thing().foo());  // 23

the given function is invoked at initialisation time for each new instance.

.init(fn)

defines a function to be called on initialisation. shorthand for .meth('_init_', fn).

var thing = strain().init(function() {
  this.foo = 'bar'
});


console.log(thing().foo);  // bar

.invoke(fn)

defines the function that is called when the instance is called. shorthand for .meth('_invoke_', fn).

var t = strain().invoke(function() {
  return 23;
})();


console.log(t());  // 23

.instanceof(instance, type)

determines whether the instance is an instance of type, regardless of whether instance and type are strain-based or not.

var foo = strain();
var bar = function() {};
console.log(strain.instanceof(foo(), foo));  // true
console.log(strain.instanceof(new bar(), bar));  // true

<instance>.prop(name[, value])

gets or sets a property by its name.

var thing = strain().prop('foo')
console.log(thing().prop('foo', 'bar').prop('foo'));  // bar

<instance>.props()

returns a shallow copy of the strain instances's properties as a data object.

var thing = strain()
  .prop('foo')
  .prop('bar');

var t = thing()
  .foo(2)
  .bar(3);

console.log(t.props());  // { foo: 2, bar: 3 }

<instance>.toJSON()

an alias to .props for stringifying the strain instance with JSON.stringify().

var thing = strain()
  .prop('foo')
  .prop('bar');

var t = thing()
  .foo(2)
  .bar(3);

console.log(JSON.stringify(t));  // {"foo":2,"bar":3}

<instance>.invoke([arg1[, arg2[, ...]]])

calls the instance with the given args.

strain()
  .invoke(function(arg) {
    console.log(arg);
  })
  .new()
  .invoke('foo');  // foo

<instance>.instanceof(type)

determines whether calling instance is an instance of the given type.

function thing() {}
var subthing = strain(thing);
var t = subthing();
console.log(t.instanceof(thing));  // true
console.log(t.instanceof(t));  // false

this is a workaround, since there is no easy, portable way to construct a callable with a properly set up prototype chain in js.

install

You can use this library as the npm package strain:

npm i strain
# or
yarn add strain

It can be used in both es-module-aware and commonjs bundlers/environments.

// es module
import strain from 'strain'

strain()
  .prop('foo')

// commonjs
const strain = require('strain')

strain()
  .prop('foo')