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

emod

v1.0.0

Published

Modelling with ES6 class support

Downloads

19

Readme

EMod: EMCAScript Modelling utility

Bring your javascript code into 2022

This package brings the benefits of axiomatic classes to existing ES6 classes. We hope that this README.md will convey the benefits of axiomatic classes and why this is a great addition to any existing or new ES6 project.

Quick Start / Demonstration of Usefulness

When using the decorator pattern it is useful to have a base class called a "Proxy". Here's what that looks like without EMod.

class Greeter {
    constructor (subject) { this.subject = subject; }
    sayHello () { return `Hello, ${this.subject}!`; }
    sayGoodbye () { return `Goodbye, ${this.subject}!`; }
}
class ProxyGreeter {
    constructor (delegate) { this.delegate = delegate; }
    sayHello () { return this.delegate.sayHello(); }
    sayGoodbye () { return this.delegate.sayGoodbye(); }
}
class ExcitedHelloGreeter extends ProxyGreeter {
    sayHello () { return this.delegate.sayHello().toUpperCase() }
}

ProxyGreeter allows a decorator to only override specific methods. This saves us having to update every decorator when Greeter is changed, however the same problem still exists elsewhere.

  • Adding/removing a method on Greeter requires updating ProxyGreeter
  • This problem is multiplied by the number of classes uising a Proxy
  • This problem is also multiplied by types of utility classes
    • Imagine NullGreeter, GreeterBuilder, GreeterComponent, etc

If we have proxies for many classes, this doesn't scale well. Worse yet, Proxy is not the only utility class you might have. You may have Null versions of classes, optimized deserializers, and so forth.

Here's the same example using EMod.

const { EM } = require('emod');
class Greeter {
    constructor (subject) { this.subject = subject; }
    sayHello () { return `Hello, ${this.subject}!`; }
    sayGoodbye () { return `Goodbye, ${this.subject}!`; }
}
class ExcitedHelloGreeter extends EM.createProxy(Greeter) {
    sayHello () { return this.delegate_.sayHello().toUpperCase() }
}

In this example ProxyGreeter already exists implicitly because there is a class named Greeter. We get it using EM.createProxy(Greeter). We may also wish the store that in a constant named ProxyGreeter.

Because 'Greeter' can be turned into a model, the Greeter class can gain new functionality without any code being added to it! It already has a Proxy class; imagine UI generators, SQL generators, etc - all generated from Greeter.

Diving Deeper

So, how does this work?

Behind the scenes the EM utility is converting the Greeter class into a model first, and then using another builtin utility to make the proxy.

const { Model, ProxyModeller, Class } = require('emod');
// ... class Greeter { ... } ...
const modelForGreeter = Model.fromClass(Greeter);
const modelForProxy = ProxyModeller.fromModel(modelForGreeter, { deep: true });
const ProxyGreeter = Class.fromModel(modelForProxy);

modelForGreeter:

{
  name: 'Greeter',
  properties: [],
  methods: [
    { name: 'sayHello', instance: sayHello () {
        return `Hello, ${this.subject}!`; } },
    { name: 'sayGoodbye', instance: sayGoodbye () {
        return `Goodbye, ${this.subject}!`; } }
  ]
}

modelForProxy:

{
  name: 'ProxyGreeter',
  properties: [
    {
      name: 'delegate',
      setter: [Function: setter],
      getter: [Function: getter]
    }
  ],
  methods: [
    { name: 'sayHello', instance: function (...a) {
        return this.delegate_.sayHello(...a) } },
    { name: 'sayGoodbye', instance: function (...a) {
        return this.delegate_.sayGoodbye(...a) } },
    { name: 'init', instance: function () {
        if ( ! this.delegate_ ) {
            this.delegate_ = new Null.fromModel(modelForGreeter)();
        }
    } }
  ]
}

Background

What is an axiomatic class?

An axiomatic class is defined using models. You may be familiar with models in frameworks like these: Django, Rails, Entity Framework.

By modelling your classes, you allow your classes to gain new features over time without adding any code to them explicitly. This is because models are essentially just data: from a modelled class you can generate database schemas, user interfaces, other utility classes, parsers, DSLs, and the list goes on.

EMod's class models are axiomatic. This means the model is built up from smaller components called axioms. Properties and methods are examples of axioms, however it is possible to define more axioms after a class is converted to a model. Think about this like attaching additional data to your class which new features can later build upon to imply functionality - functionality that you never had to write manually!

Some Backstory

In 2016, Kevin G. R. Greer, a famous computer scientist, wrote this article describing how the origins of Javascript's prototypical inheritance reveal dormant modelling capabilities within the language. This is key to understanding the motivation behind his framework FOAM (Feature-Oriented Active Modeller).

The implementation of axiomatic class models used by EMod is inspired by FOAM. Kevin attributes the idea of axiomatic classes to a family of languages called Description Logics.

FOAM is packed with features including a common interface for data access, code generation targeting Java and Swift, and much more. EMod, in contrast, intends to be a tiny utility that does nothing more than provide modelling.