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

fusium-js

v0.3.1

Published

A tiny class-based composition/mixin library

Downloads

28

Readme

Fusium

Class based composition/Mix-Ins in TS & JS made intuitive, elegant and powerful. If you have missed multiple inheritance in TS, you have missed this library.

Write Classes that describe Traits of objects and compose those traits to form new, more complex types. If you don't like the official Mix-In syntax and its constraints, this library offers a viable (but experimental) alternative.

State of the project

This project is experimental and is only roughly tested on V8 based platforms so far.

Introduction

In object-oriented programming, composition is a design principle that allows for the creation of complex types by combining simpler, more focused types. Unlike inheritance, which defines a class in terms of another class, composition defines a class as containing instances of other classes. This approach offers several benefits:

  • Modularity: By breaking down functionality into smaller, reusable components, code becomes more organized and easier to manage.
  • Flexibility: Components can be easily replaced or updated without affecting the overall system.
  • Maintainability: Smaller, well-defined components are easier to understand, test, and debug.
  • Avoidance of Inheritance Pitfalls: Composition avoids issues like the fragile base class problem and deep inheritance hierarchies that can make code brittle and difficult to refactor.

The Fusium Composition Library leverages TypeScript's advanced type system together with JS proxies to provide a powerful and type-safe way to compose classes. It allows developers to fuse multiple classes into a single one, combining their behaviors and properties without the drawbacks of traditional inheritance.

Core Concepts

This library is tiny and builds on top of three main ideas:

  • Composable/Trait: A Trait or Composable (they are equivalent, but just differently named to aid semantics in certain contexts) is a group of functionality and data that can be composed together. In practice this is bundled together as an ES6-class and can be either used standalone if sufficient or in a Fusion. Traits may for example be deletable, writable etc.
  • Fusions: A Fusion is the composition or combination of multiple Traits into either a more complex Trait or an Object that exhibits these Traits. A super-trait like "streamable" may, for example, be composed of Traits like asynchronous and cancellable and thus would be a Fusion of the two. An Object exhibiting these traits may for example be a Document that is a Fusion of the writable and deletable Traits.
  • Co-Traits: Sometimes certain Traits need to make assumptions about their "environment". Looking at an example: UIElement for instance could be an Object that may be draggable. This implies, however, that the element is movable, and thus has a position on screen - and the draggable trait will try to interact with that position in a way. It thus requires the traits positioned, movable and pointable to be other traits of an object that wants to have the draggable trait. positioned, pointable and moveable would be Co-Traits of draggable. draggable assumes these traits and UIElement must be a Fusion of at least these three traits together.

Installation

Fusium is just an npm install away:

npm install fusium-js

Usage Examples

Here's a simple pseudo-code example concretizing the concepts above to compose a UIElement:

import { Trait, CoTraits, FusionOf } from "fusium-js";

// Define the UIElement as a Fusion/Composition of the traits
// Not that UIElement does not contain any logic for wiring traits together as the traits
// already know their environment and how to interact with each other through their defined "Co-Traits"
class UIElement extends FusionOf(Draggable, Movable, Pointable, Positioned) {
    constructor()
    {
        this.onPositionChanged(() => { /*...reRendering logic...*/});
    }
}

// Define the individual traits as classes that extend from Trait
class Positioned extends Trait 
{
  protected x: number;
  protected y: number;
  public onPositionChanged = new EventEmitter();

  setPosition(x, y) {...}
}

// This trait assumes and works with the x and y coordinates from the Co-Trait `Positioned`
class Movable extends CoTraits(Positioned)   
{
  move(dx: number, dy: number) {
    this.setPosition(this.x + dx, this.y + dy);
  }
}

// Note that in order to be Composable, a class (or the base end of its inheritance chain) needs to derive from `Composable` or `Trait`
class Pointable extends Trait   
{
  constructor()
  {
    environment.trackPointer(this)
  }

    onPointerPressed = new EventEmitter();
    onPointerReleased = new EventEmitter();
    onPointerMove = new EventEmitter();
}

// Note that the CoTraits-Function serves very little purpose on JS level (it's a typed Placeholder for `Trait`), but rather helps with type-safety on TS level
// Only the FusionOf-Function actually composes functionality on the JS level
class Draggable extends CoTraits(Pointable, Movable) 
{
    registerListeners()
    {
        this.onPointerPressed(() => this.onPointerMove(handlePressedAndMoved));
    }

    handlePressedAndMoved(dx, dy)
    {
        this.move(dx, dy);
    }
}

Performance

This library should have little effect on runtime performance, except from marginal slow-down in object definition (as the types are composed once you call the "FusionOf"-Function) and object instantiation (single-line constructor-proxy). The resultant classes should still be optimizable by V8 etc. as the prototype chain remains flat and static once "FusionOf" was called, which normally happens while "parsing"/initially running a module.

Contribution

For now this project is experimental - thus your feedback and input and thoughts are highly appreciated.

License

Fusium is open-source software licensed under the MIT License. This means you're free to use, modify, and distribute the library, provided you include the original license and copyright notice in any copies or substantial portions of the software.