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 🙏

© 2026 – Pkg Stats / Ryan Hefner

mixin-flavors

v0.4.1

Published

LISP-flavored mixins and object system for JS

Readme

Flavors object model for JS (development preview)

Mixin engine for modern JS and TypeScript inspired by Howard I. Cannon work for MIT Lisp Machine as described in Flavors: A non-hierarchical approach to object-oriented programming.

write something about origins of Flawors and problems it solves

Installation

npm install mixin-flavors

Basic usage

In its basic use case, FlavorsJS gives you multiple inheritance in JS.

join( Base, B, ... )

Produce a new class which is a combination of given classes. Resulting class will be the proper subclass of Base merging in the prototype methods of other classes. Resulting class constructor will call the Base constructor with a same set of arguments, and mixin constructors with no arguments in a same order mixins are mentioned (??).

join operation is meant to be used in conjunction with class extends to implement multiple inheritance.

class A {
    a = 1;
    f(){
        return 'a';
    }
}

class B {
    b = 1;

    g(){
        return 'b';
    }
}

class C extends join( A, B ){
    g(){
        return 'c'
    }
}

const c = new C();

expect( c.a ).toBe( 1 )
expect( c.b ).toBe( 1 )
expect( c.f() ).toBe( 'a' )
expect( c.g() ).toBe( 'c' )

@mixin.extends( A, B, ... )

Merge methods of given classes to the existing class definition.

Use mixin.super( this ) to call all the mixins constructors with no arguments, or call them inidividually with A.call( this ), B.call( this ), etc.

class A {
    a = 1;

    f(){
        return 'a';
    }
}

class B {
    b = 1;

    g(){
        return 'b';
    }
}

@mixin.extends( A, B )
class C {
    constructor(){
        mixin.super( this );
    }

    g(){
        return 'c'
    }
}

const c = new C();

expect( c.a ).toBe( 1 )
expect( c.b ).toBe( 1 )
expect( c.f() ).toBe( 'a' )
expect( c.g() ).toBe( 'c' )

Advanced usage: method combinations

FlavorsJS implements method combinations as found in Common LISP Object System and Flavors system from MIT LISP Machine. Combinations are special rules for merging methods with a same name found in different mixins. There are four combinations available:

  • primary methods, the most common combination demonstrated in Basic Usage section. Every method is primary by default and when there are many of them coming from mixins the forst one is taken. Primary method in a subclass overrides primary methods in base classes. That's how the mixins should work according to a common knowledge.
  • before methods, which are a hooks executed before the primary method in the same order as they appear in mixins list.
  • after methods, which are a hooks executed after the primary method in the opposite order as they appear in mixins list.
  • around methods, which wrap the primary method calls.

In order for method combinations to work, all target class declaration must be preceded with @mixin decorator or use @mixin.extends option to merge mixins.

When using @mixin decorator a base class is treated just like another mixin, so it's possible to use standard class extends together with @mixin/@mixin.extends decorator and all method combinations will be aplied properly. Also, it's possible to add method combinations is a subclass or mixin target.

@before method( a, b, ... ){ ... }

Execute the given function before the method will be called. Receives the same set of arguments, the return value is ignored. If there are many before methods coming from different mixins, they will be executed in the same order as they appear in mixins.

class ExtendState {
    @after componentWillMount(){
        this.state.something = "Hi";
    }
}

@mixin class B extends join( React.Component, ExtendState ){
    componentWillMount(){
        this.state = { text : 'Hello' };
    }
    ...
}

// or, as an alternative
@mixin.extends( ExtendState )
class B extends React.Component {
    componentWillMount(){
        this.state = { text : 'Hello' };
    }
    ...
}

// or, as another alternative
@mixin class ExtendState extends React.Component{
    @after componentWillMount(){
        this.state.something = "Hi";
    }
}

@mixin class B extends ExtendState {
    componentWillMount(){
        this.state = { text : 'Hello' };
    }
    ...
}

@before.do( aspect ) method( a, b, ... ){ ... }

The generalized form of @before attaching the before aspect represented as function to the given primary method. Think of it as a single-function mixins.

function extendState(){
    this.state.something = "Hi";
}

@mixin class B extends React.Component{
    @before.do( extendState )
    componentWillMount(){
        this.state = { text : 'Hello' };
    }
    ...
}

@after method( a, b, ... ){ ... }

Execute the given function after the method will be called. Receives the same set of arguments, the return value is ignored. If there are many after methods coming from different mixins, they will be executed in the opposite order as they appear in mixins.

@mixin class EventfulComponent extends Messenger {
    @after componentWillUnmount(){
        this.stopListening()
    }
}

class MyComponent extends join( React.Component, EventfulComponent ) {
    componentWillUnmount(){
        console.log( 'Unmounting' );
    }
}

@after.do( aspect ) method( a, b, ... ){ ... }

The generalized form of @after attaching the after aspect represented as function to the given primary method. Think of it as a single-function mixins.

function unsubscribe(){
    this.stopListening()
}

@mixin class MyComponent extends join( React.Component, Messenger ) {
    
    @after.do( unsubscribe )
    componentWillUnmount(){
        console.log( 'Unmounting' );
    }
}

@around method( a, b, ... ){ ... }

Wrap the method call into the given function. The original method can be called with mixin.nextMethod( a, b, ... ) or mixin.applyNextMethod() to call it with the original set of arguments.

class A {
    @around shouldComponentUpdate( nextProps ){
        return applyNextMethod() && nextProps.a !== this.props.a;
    }
}

@mixin class B extends join( React.Component, A ){
    ...

    shouldComponentUpdate( nextProps ){
        return nextProps.b !== this.props.b;
    }
}

@around.do( aspect ) method( a, b, ... ){ ... }

The generalized form of @around.

class A {
    @around.do(
        function( nextProps ){
            return mixin.applyNextMethod() && nextProps.a !== this.props.a;
        }
    )
    shouldComponentUpdate( nextProps ){ // Provide the default shouldComponentUpdate implementation.
        return true;
    }
}

@mixin class B extends join( React.Component, A ){
    ...

    shouldComponentUpdate( nextProps ){
        return nextProps.b !== this.props.b;
    }
}

TODO: Properties combinations

@after.set( fun ) prop

Execute the given function after the value has changed.

class Observer {
    @after.set( function(){
        console.log( `I see you, ${ this.value }!` );
    }) value;
}

@mixin.extends( Observer )
class B {
    ...

    doSomething(){
        this.value = 5; // Will print "I see you, 5"
    }
}

@before.set( fun ) prop

Execute the given function before the value has changed.

class Observer {
    @before.set( function( x ){
        console.log( `I see you last time, ${ x }!` );
    }) value;
}

@mixin.extends( Observer )
class B {
    ...

    doSomething(){
        this.value = 5; // Will print "I see you, 5"
    }
}

@around.set( fun ) prop

Tap into the property modification process.

class Observer {
    @around.set( function( x ){
        callNextFunction( Number( x ) );
    }) value;
}

@mixin.extends( Observer )
class B {
    ...

    doSomething(){
        this.value = 5; // Will print "I see you, 5"
    }
}