Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mixinable

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mixinable - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

12

CHANGELOG.md

@@ -5,2 +5,14 @@ # Change Log

<a name="1.1.0"></a>
# [1.1.0](https://github.com/dmbch/mixinable/compare/v0.4.0...v1.1.0) (2017-11-23)
### Features
* accept constructor functions as definitions ([05fa890](https://github.com/dmbch/mixinable/commit/05fa890))
* add compose strategy ([81d1e14](https://github.com/dmbch/mixinable/commit/81d1e14))
* add override strategy, refactor and simplify ([a49b613](https://github.com/dmbch/mixinable/commit/a49b613))
<a name="1.0.0"></a>

@@ -7,0 +19,0 @@ # [1.0.0](https://github.com/dmbch/mixinable/compare/3799c885...v1.0.0) (2017-11-21)

91

index.js
'use strict';
module.exports = exports = function define (definition) {
var methodNames = getMethodNames(definition);
var mixinable = createMixinable(definition, methodNames);
var mixinable = createMixinable(definition);
return function mixin () {
var mixins = argsToArray(arguments).map(createClass);
var mixins = argsToArray(arguments).map(createMixin);
return function create () {
var args = argsToArray(arguments);
var mixinstances = mixins.map(function (mixin) {
return new (mixin.bind.apply(mixin, [mixin].concat(args)))();
return new (bindArgs(mixin, args))();
});
return Object.defineProperties(
new (mixinable.bind.apply(mixinable, [mixinable].concat(args)))(),
new (bindArgs(mixinable, args))(),
{
__implementations__: {
value: getImplementations(mixinstances, methodNames)
value: getImplementations(mixinable, mixinstances)
},
__clone__: {
value: create.bind.apply(create, [create].concat(args))
value: bindArgs(create, args)
}

@@ -28,2 +27,4 @@ }

// strategy exports
exports.override = function override (functions) {

@@ -64,2 +65,10 @@ var args = argsToArray(arguments).slice(1);

exports.compose = function compose (_functions) {
var args = argsToArray(arguments).slice(1);
var functions = [].concat(_functions).reverse();
return exports.pipe.apply(null, [functions].concat(args));
};
// utility exports
exports.clone = function clone (instance) {

@@ -72,31 +81,38 @@ var args = argsToArray(arguments).slice(1);

function createMixinable (definition, methodNames) {
return createClass(
methodNames.reduce(function (result, methodName) {
if (methodName === 'constructor') {
result[methodName] = definition[methodName];
} else {
result[methodName] = function () {
// classy helpers
function createMixinable (definition) {
var prototype = getPrototype(definition);
return Object.assign(function Mixinable () {
getConstructor(definition).apply(this, arguments);
}, {
prototype: Object.assign(
Object.create(prototype),
Object.keys(prototype).reduce(function (result, key) {
result[key] = function () {
var args = argsToArray(arguments);
var functions = this.__implementations__[methodName];
return definition[methodName].apply(null, [functions].concat(args));
var functions = this.__implementations__[key];
var strategy = prototype[key];
return strategy.apply(this, [functions].concat(args));
};
}
return result;
}, {})
);
return result;
}, {})
)
});
}
function createClass (prototype) {
var constructor = function () {};
if (prototype.hasOwnProperty('constructor')) {
constructor = prototype.constructor;
function createMixin (definition) {
if (isFunction(definition)) {
return definition;
} else {
prototype.constructor = constructor;
return Object.assign(function Mixin () {
getConstructor(definition).apply(this, arguments);
}, {
prototype: getPrototype(definition)
});
}
constructor.prototype = prototype;
return constructor;
}
function getImplementations (mixinstances, methodNames) {
function getImplementations (mixinable, mixinstances) {
var methodNames = Object.keys(mixinable.prototype);
return methodNames.reduce(function (result, methodName) {

@@ -114,8 +130,3 @@ result[methodName] = mixinstances

function getMethodNames (definition) {
return Object.keys(definition || {})
.filter(function (methodName) {
return isFunction(definition[methodName]);
});
}
// utilities

@@ -133,2 +144,14 @@ var argsToArray = Function.prototype.apply.bind(

function bindArgs (fn, args) {
return Function.prototype.bind.apply(fn, [fn].concat(args));
}
function getConstructor (def) {
return (def && ((isFunction(def)) ? def : def.constructor)) || function () {};
}
function getPrototype (def) {
return (def && ((isFunction(def)) ? def.prototype : def)) || {};
}
function isFunction (obj) {

@@ -135,0 +158,0 @@ return typeof obj === 'function';

{
"name": "mixinable",
"version": "1.0.0",
"version": "1.1.0",
"description": "Functional JavaScript Mixin Utility",

@@ -9,3 +9,3 @@ "main": "index.js",

"release": "standard-version",
"postrelease": "npm publish --registry https://registry.npmjs.org/"
"postrelease": "git push --follow-tags; npm publish --registry https://registry.npmjs.org/"
},

@@ -12,0 +12,0 @@ "repository": {

@@ -231,3 +231,20 @@ # Mixinable

#### ```define.compose```
`compose` works essentially identically as `pipe`, but in reverse order: the very last implementation receives the initial value and the first implementation returns the final output.
##### Example
```javascript
import define, { compose } from 'mixinable';
const mixin = define({
// mixin strategy function
bar: compose
});
// ...
```
#### Custom Strategies

@@ -234,0 +251,0 @@

@@ -71,2 +71,49 @@ 'use strict';

test('inheritance test', function (t) {
t.plan(15);
var arg = 1;
function Strategy (_arg) {
t.pass('strategy constructor is being called');
t.equal(_arg, arg, 'strategy constructor receives correct arg');
t.ok(this instanceof Strategy, 'strategy inherits correctly');
t.ok(
Strategy.prototype.isPrototypeOf(this),
'strategy prototype chain is set up'
);
}
Strategy.prototype = {
foo: function (functions, _arg) {
t.equal(_arg, arg, 'strategy definition receives correct arg');
t.ok(this instanceof Strategy, 'strategy inherits correctly');
t.ok(
Strategy.prototype.isPrototypeOf(this),
'strategy prototype chain is set up'
);
functions.forEach(function (fn) { fn(_arg); });
}
};
function Implementation (_arg) {
t.pass('implementation constructor is being called');
t.equal(_arg, arg, 'implementation constructor receives correct arg');
t.ok(this instanceof Implementation, 'implementation inherits correctly');
t.ok(
Implementation.prototype.isPrototypeOf(this),
'implementation prototype chain is set up'
);
}
Implementation.prototype = {
foo: function (_arg) {
t.pass('implementation is being called');
t.equal(_arg, arg, 'implementation receives correct arg');
t.ok(this instanceof Implementation, 'implementation inherits correctly');
t.ok(
Implementation.prototype.isPrototypeOf(this),
'implementation prototype chain is set up'
);
}
};
var instance = mixinable(Strategy)(Implementation)(arg);
instance.foo(arg);
});
test('override helper test', function (t) {

@@ -311,1 +358,103 @@ t.plan(2);

});
test('sync compose helper test', function (t) {
t.plan(10);
var arg = 1;
var instance = mixinable(
{
foo: mixinable.compose
}
)(
{
foo: function (ctr, _arg) {
t.equal(ctr, 2, '1st implementation receives 2nd\'s result');
t.equal(_arg, arg, '1st implementation receives correct arg');
return this.increment(ctr);
},
increment: function (ctr) {
t.pass('1st private method is being called');
return ++ctr;
}
},
{
foo: function (ctr, _arg) {
t.equal(ctr, 1, '2nd implementation receives 1st\'s result');
t.equal(_arg, arg, '2nd implementation receives correct arg');
return this.increment(ctr);
},
increment: function (ctr) {
t.pass('2nd private method is being called');
return ++ctr;
}
},
{
foo: function (ctr, _arg) {
t.equal(ctr, 0, '3rd implementation receives inital value');
t.equal(_arg, arg, '3rd implementation receives correct arg');
return this.increment(ctr);
},
increment: function (ctr) {
t.pass('3rd private method is being called');
return ++ctr;
}
}
)();
t.equal(instance.foo(0, arg), 3, 'correct result received');
});
test('async compose helper test', function (t) {
t.plan(11);
var arg = 1;
var instance = mixinable(
{
foo: mixinable.compose
}
)(
{
foo: function (ctr, _arg) {
t.equal(ctr, 2, '1st implementation receives 2nd\'s result');
t.equal(_arg, arg, '1st implementation receives correct arg');
return this.increment(ctr);
},
increment: function (ctr) {
t.pass('1st private method is being called');
return ++ctr;
}
},
{
foo: function (ctr, _arg) {
t.equal(ctr, 1, '2nd implementation receives 1st\'s result');
t.equal(_arg, arg, '2nd implementation receives correct arg');
return new Promise(function (resolve) {
setTimeout(function () {
resolve(this.increment(ctr));
}.bind(this), 5);
}.bind(this));
},
increment: function (ctr) {
t.pass('2nd private method is being called');
return ++ctr;
}
},
{
foo: function (ctr, _arg) {
t.equal(ctr, 0, '3rd implementation receives inital value');
t.equal(_arg, arg, '3rd implementation receives correct arg');
return new Promise(function (resolve) {
setTimeout(function () {
resolve(this.increment(ctr));
}.bind(this), 10);
}.bind(this));
},
increment: function (ctr) {
t.pass('3rd private method is being called');
return ++ctr;
}
}
)();
var result = instance.foo(0, arg);
t.ok(result instanceof Promise, 'received result is a promise');
result.then(function (result) {
t.equal(result, 3, 'promise resolves to correct value');
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc